Merge remote-tracking branch 'upstream-ti-android-linux-4.14.y' into android-beagle-x15-4.14

* upstream-ti-android-linux-4.14.y:
  Linux 4.14.213
  PCI: Fix pci_slot_release() NULL pointer dereference
  libnvdimm/namespace: Fix reaping of invalidated block-window-namespace labels
  xenbus/xenbus_backend: Disallow pending watch messages
  xen/xenbus: Count pending messages for each watch
  xen/xenbus/xen_bus_type: Support will_handle watch callback
  xen/xenbus: Add 'will_handle' callback support in xenbus_watch_path()
  xen/xenbus: Allow watches discard events before queueing
  xen-blkback: set ring->xenblkd to NULL after kthread_stop()
  clk: mvebu: a3700: fix the XTAL MODE pin to MPP1_9
  md/cluster: fix deadlock when node is doing resync job
  iio:imu:bmi160: Fix too large a buffer.
  iio:pressure:mpl3115: Force alignment of buffer
  iio:light:rpr0521: Fix timestamp alignment and prevent data leak.
  iio: adc: rockchip_saradc: fix missing clk_disable_unprepare() on error in rockchip_saradc_resume
  iio: buffer: Fix demux update
  mtd: parser: cmdline: Fix parsing of part-names with colons
  soc: qcom: smp2p: Safely acquire spinlock without IRQs
  spi: st-ssc4: Fix unbalanced pm_runtime_disable() in probe error path
  spi: sc18is602: Don't leak SPI master in probe error path
  spi: rb4xx: Don't leak SPI master in probe error path
  spi: pic32: Don't leak DMA channels in probe error path
  spi: davinci: Fix use-after-free on unbind
  spi: spi-sh: Fix use-after-free on unbind
  drm/dp_aux_dev: check aux_dev before use in drm_dp_aux_dev_get_by_minor()
  jfs: Fix array index bounds check in dbAdjTree
  jffs2: Fix GC exit abnormally
  ceph: fix race in concurrent __ceph_remove_cap invocations
  ima: Don't modify file descriptor mode on the fly
  powerpc/powernv/memtrace: Don't leak kernel memory to user space
  powerpc/xmon: Change printk() to pr_cont()
  powerpc/rtas: Fix typo of ibm,open-errinjct in RTAS filter
  ARM: dts: at91: sama5d2: fix CAN message ram offset and size
  KVM: arm64: Introduce handling of AArch32 TTBCR2 traps
  ext4: fix deadlock with fs freezing and EA inodes
  ext4: fix a memory leak of ext4_free_data
  btrfs: fix return value mixup in btrfs_get_extent
  Btrfs: fix selftests failure due to uninitialized i_mode in test inodes
  USB: serial: keyspan_pda: fix write unthrottling
  USB: serial: keyspan_pda: fix tx-unthrottle use-after-free
  USB: serial: keyspan_pda: fix write-wakeup use-after-free
  USB: serial: keyspan_pda: fix stalled writes
  USB: serial: keyspan_pda: fix write deadlock
  USB: serial: keyspan_pda: fix dropped unthrottle interrupts
  USB: serial: mos7720: fix parallel-port state restore
  EDAC/amd64: Fix PCI component registration
  crypto: ecdh - avoid unaligned accesses in ecdh_set_secret()
  powerpc/perf: Exclude kernel samples while counting events in user space.
  staging: comedi: mf6x4: Fix AI end-of-conversion detection
  s390/dasd: fix list corruption of lcu list
  s390/dasd: fix list corruption of pavgroup group list
  s390/dasd: prevent inconsistent LCU device data
  s390/smp: perform initial CPU reset also for SMT siblings
  ALSA: usb-audio: Disable sample read check if firmware doesn't give back
  ALSA: pcm: oss: Fix a few more UBSAN fixes
  ALSA: hda/realtek - Enable headset mic of ASUS Q524UQK with ALC255
  ACPI: PNP: compare the string length in the matching_id()
  Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources walks"
  PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup()
  Input: cyapa_gen6 - fix out-of-bounds stack access
  media: netup_unidvb: Don't leak SPI master in probe error path
  media: sunxi-cir: ensure IR is handled when it is continuous
  media: gspca: Fix memory leak in probe
  Input: goodix - add upside-down quirk for Teclast X98 Pro tablet
  Input: cros_ec_keyb - send 'scancodes' in addition to key events
  fix namespaced fscaps when !CONFIG_SECURITY
  cfg80211: initialize rekey_data
  clk: sunxi-ng: Make sure divider tables have sentinel
  clk: s2mps11: Fix a resource leak in error handling paths in the probe function
  qlcnic: Fix error code in probe
  perf record: Fix memory leak when using '--user-regs=?' to list registers
  pwm: lp3943: Dynamically allocate PWM chip base
  pwm: zx: Add missing cleanup in error path
  clk: ti: Fix memleak in ti_fapll_synth_setup
  watchdog: coh901327: add COMMON_CLK dependency
  watchdog: qcom: Avoid context switch in restart handler
  net: korina: fix return value
  net: allwinner: Fix some resources leak in the error handling path of the probe and in the remove function
  net: bcmgenet: Fix a resource leak in an error handling path in the probe functin
  checkpatch: fix unescaped left brace
  powerpc/ps3: use dma_mapping_error()
  nfc: s3fwrn5: Release the nfc firmware
  um: chan_xterm: Fix fd leak
  watchdog: sirfsoc: Add missing dependency on HAS_IOMEM
  irqchip/alpine-msi: Fix freeing of interrupts on allocation error path
  ASoC: wm_adsp: remove "ctl" from list on error in wm_adsp_create_control()
  extcon: max77693: Fix modalias string
  clk: tegra: Fix duplicated SE clock entry
  x86/kprobes: Restore BTF if the single-stepping is cancelled
  nfs_common: need lock during iterate through the list
  nfsd: Fix message level for normal termination
  speakup: fix uninitialized flush_lock
  usb: oxu210hp-hcd: Fix memory leak in oxu_create
  usb: ehci-omap: Fix PM disable depth umbalance in ehci_hcd_omap_probe
  powerpc/pseries/hibernation: remove redundant cacheinfo update
  powerpc/pseries/hibernation: drop pseries_suspend_begin() from suspend ops
  scsi: fnic: Fix error return code in fnic_probe()
  seq_buf: Avoid type mismatch for seq_buf_init
  scsi: pm80xx: Fix error return in pm8001_pci_probe()
  scsi: qedi: Fix missing destroy_workqueue() on error in __qedi_probe
  cpufreq: scpi: Add missing MODULE_ALIAS
  cpufreq: loongson1: Add missing MODULE_ALIAS
  cpufreq: st: Add missing MODULE_DEVICE_TABLE
  cpufreq: mediatek: Add missing MODULE_DEVICE_TABLE
  cpufreq: highbank: Add missing MODULE_DEVICE_TABLE
  clocksource/drivers/arm_arch_timer: Correct fault programming of CNTKCTL_EL1.EVNTI
  dm ioctl: fix error return code in target_message
  ASoC: jz4740-i2s: add missed checks for clk_get()
  net/mlx5: Properly convey driver version to firmware
  memstick: r592: Fix error return in r592_probe()
  arm64: dts: rockchip: Fix UART pull-ups on rk3328
  pinctrl: falcon: add missing put_device() call in pinctrl_falcon_probe()
  ARM: dts: at91: sama5d2: map securam as device
  clocksource/drivers/cadence_ttc: Fix memory leak in ttc_setup_clockevent()
  media: saa7146: fix array overflow in vidioc_s_audio()
  vfio-pci: Use io_remap_pfn_range() for PCI IO memory
  NFS: switch nfsiod to be an UNBOUND workqueue.
  lockd: don't use interval-based rebinding over TCP
  SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
  NFSv4.2: condition READDIR's mask for security label based on LSM state
  ath10k: Release some resources in an error handling path
  ath10k: Fix an error handling path
  ARM: dts: at91: at91sam9rl: fix ADC triggers
  PCI: iproc: Fix out-of-bound array accesses
  genirq/irqdomain: Don't try to free an interrupt that has no mapping
  power: supply: bq24190_charger: fix reference leak
  ARM: dts: Remove non-existent i2c1 from 98dx3236
  HSI: omap_ssi: Don't jump to free ID in ssi_add_controller()
  media: max2175: fix max2175_set_csm_mode() error code
  mips: cdmm: fix use-after-free in mips_cdmm_bus_discover
  samples: bpf: Fix lwt_len_hist reusing previous BPF map
  media: siano: fix memory leak of debugfs members in smsdvb_hotplug
  cw1200: fix missing destroy_workqueue() on error in cw1200_init_common
  orinoco: Move context allocation after processing the skb
  ARM: dts: at91: sama5d3_xplained: add pincontrol for USB Host
  ARM: dts: at91: sama5d4_xplained: add pincontrol for USB Host
  memstick: fix a double-free bug in memstick_check
  RDMA/cxgb4: Validate the number of CQEs
  Input: omap4-keypad - fix runtime PM error handling
  drivers: soc: ti: knav_qmss_queue: Fix error return code in knav_queue_probe
  soc: ti: Fix reference imbalance in knav_dma_probe
  soc: ti: knav_qmss: fix reference leak in knav_queue_probe
  crypto: omap-aes - Fix PM disable depth imbalance in omap_aes_probe
  powerpc/feature: Fix CPU_FTRS_ALWAYS by removing CPU_FTRS_GENERIC_32
  Input: ads7846 - fix unaligned access on 7845
  Input: ads7846 - fix integer overflow on Rt calculation
  Input: ads7846 - fix race that causes missing releases
  drm/omap: dmm_tiler: fix return error code in omap_dmm_probe()
  media: solo6x10: fix missing snd_card_free in error handling case
  scsi: core: Fix VPD LUN ID designator priorities
  media: mtk-vcodec: add missing put_device() call in mtk_vcodec_release_dec_pm()
  staging: greybus: codecs: Fix reference counter leak in error handling
  MIPS: BCM47XX: fix kconfig dependency bug for BCM47XX_BCMA
  RDMa/mthca: Work around -Wenum-conversion warning
  ASoC: arizona: Fix a wrong free in wm8997_probe
  ASoC: wm8998: Fix PM disable depth imbalance on error
  mwifiex: fix mwifiex_shutdown_sw() causing sw reset failure
  spi: tegra114: fix reference leak in tegra spi ops
  spi: tegra20-sflash: fix reference leak in tegra_sflash_resume
  spi: tegra20-slink: fix reference leak in slink ops of tegra20
  spi: spi-ti-qspi: fix reference leak in ti_qspi_setup
  Bluetooth: Fix null pointer dereference in hci_event_packet()
  arm64: dts: exynos: Correct psci compatible used on Exynos7
  selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
  ASoC: pcm: DRAIN support reactivation
  spi: img-spfi: fix reference leak in img_spfi_resume
  crypto: talitos - Fix return type of current_desc_hdr()
  sched: Reenable interrupts in do_sched_yield()
  sched/deadline: Fix sched_dl_global_validate()
  ARM: p2v: fix handling of LPAE translation in BE mode
  x86/mm/ident_map: Check for errors from ident_pud_init()
  RDMA/rxe: Compute PSN windows correctly
  selinux: fix error initialization in inode_doinit_with_dentry()
  RDMA/bnxt_re: Set queue pair state when being queried
  soc: mediatek: Check if power domains can be powered on at boot time
  soc: renesas: rmobile-sysc: Fix some leaks in rmobile_init_pm_domains()
  drm/gma500: fix double free of gma_connector
  Bluetooth: Fix slab-out-of-bounds read in hci_le_direct_adv_report_evt()
  md: fix a warning caused by a race between concurrent md_ioctl()s
  crypto: af_alg - avoid undefined behavior accessing salg_name
  media: msi2500: assign SPI bus number dynamically
  quota: Sanity-check quota file headers on load
  serial_core: Check for port state when tty is in error state
  HID: i2c-hid: add Vero K147 to descriptor override
  ARM: dts: exynos: fix USB 3.0 pins supply being turned off on Odroid XU
  ARM: dts: exynos: fix USB 3.0 VBUS control and over-current pins on Exynos5410
  ARM: dts: exynos: fix roles of USB 3.0 ports on Odroid XU
  usb: chipidea: ci_hdrc_imx: Pass DISABLE_DEVICE_STREAMING flag to imx6ul
  USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
  usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
  USB: gadget: f_midi: setup SuperSpeed Plus descriptors
  USB: gadget: f_acm: add support for SuperSpeed Plus
  USB: serial: option: add interface-number sanity check to flag handling
  soc/tegra: fuse: Fix index bug in get_process_id
  dm table: Remove BUG_ON(in_interrupt())
  scsi: mpt3sas: Increase IOCInit request timeout to 30s
  vxlan: Copy needed_tailroom from lowerdev
  vxlan: Add needed_headroom for lower device
  drm/tegra: sor: Disable clocks on error in tegra_sor_init()
  kernel/cpu: add arch override for clear_tasks_mm_cpumask() mm handling
  RDMA/cm: Fix an attempt to use non-valid pointer when cleaning timewait
  can: softing: softing_netdev_open(): fix error handling
  scsi: bnx2i: Requires MMU
  gpio: mvebu: fix potential user-after-free on probe
  ARM: dts: sun8i: v3s: fix GIC node memory range
  pinctrl: baytrail: Avoid clearing debounce value when turning it off
  pinctrl: merrifield: Set default bias in case no particular value given
  drm: fix drm_dp_mst_port refcount leaks in drm_dp_mst_allocate_vcpi
  serial: 8250_omap: Avoid FIFO corruption caused by MDR1 access
  ALSA: pcm: oss: Fix potential out-of-bounds shift
  USB: sisusbvga: Make console support depend on BROKEN
  USB: UAS: introduce a quirk to set no_write_same
  xhci: Give USB2 ports time to enter U3 in bus suspend
  ALSA: usb-audio: Fix control 'access overflow' errors from chmap
  ALSA: usb-audio: Fix potential out-of-bounds shift
  USB: add RESET_RESUME quirk for Snapscan 1212
  USB: dummy-hcd: Fix uninitialized array use in init()
  mac80211: mesh: fix mesh_pathtbl_init() error path
  net: bridge: vlan: fix error return code in __vlan_add()
  net: stmmac: dwmac-meson8b: fix mask definition of the m250_sel mux
  net: stmmac: delete the eee_ctrl_timer after napi disabled
  net/mlx4_en: Handle TX error CQE
  net/mlx4_en: Avoid scheduling restart task if it is already running
  tcp: fix cwnd-limited bug for TSO deferral where we send nothing
  net: stmmac: free tx skb buffer in stmmac_resume()
  PCI: qcom: Add missing reset for ipq806x
  x86/mm/mem_encrypt: Fix definition of PMD_FLAGS_DEC_WP
  scsi: be2iscsi: Revert "Fix a theoretical leak in beiscsi_create_eqs()"
  kbuild: avoid static_assert for genksyms
  pinctrl: amd: remove debounce filter setting in IRQ type setting
  Input: i8042 - add Acer laptops to the i8042 reset list
  Input: cm109 - do not stomp on control URB
  platform/x86: acer-wmi: add automatic keyboard background light toggle key as KEY_LIGHTS_TOGGLE
  soc: fsl: dpio: Get the cpumask through cpumask_of(cpu)
  scsi: ufs: Make sure clk scaling happens only when HBA is runtime ACTIVE
  ARC: stack unwinding: don't assume non-current task is sleeping
  iwlwifi: mvm: fix kernel panic in case of assert during CSA
  arm64: dts: rockchip: Assign a fixed index to mmc devices on rk3399 boards.
  iwlwifi: pcie: limit memory read spin time
  spi: bcm2835aux: Restore err assignment in bcm2835aux_spi_probe
  spi: bcm2835aux: Fix use-after-free on unbind
  Linux 4.14.212
  x86/uprobes: Do not use prefixes.nbytes when looping over prefixes.bytes
  Input: i8042 - fix error return code in i8042_setup_aux()
  i2c: qup: Fix error return code in qup_i2c_bam_schedule_desc()
  gfs2: check for empty rgrp tree in gfs2_ri_update
  tracing: Fix userstacktrace option for instances
  spi: bcm2835: Release the DMA channel if probe fails after dma_init
  spi: bcm2835: Fix use-after-free on unbind
  spi: bcm-qspi: Fix use-after-free on unbind
  spi: Introduce device-managed SPI controller allocation
  iommu/amd: Set DTE[IntTabLen] to represent 512 IRTEs
  speakup: Reject setting the speakup line discipline outside of speakup
  i2c: imx: Check for I2SR_IAL after every byte
  i2c: imx: Fix reset of I2SR_IAL flag
  mm/swapfile: do not sleep with a spin lock held
  cifs: fix potential use-after-free in cifs_echo_request()
  ftrace: Fix updating FTRACE_FL_TRAMP
  ALSA: hda/generic: Add option to enforce preferred_dacs pairs
  ALSA: hda/realtek - Add new codec supported for ALC897
  tty: Fix ->session locking
  tty: Fix ->pgrp locking in tiocspgrp()
  USB: serial: option: fix Quectel BG96 matching
  USB: serial: option: add support for Thales Cinterion EXS82
  USB: serial: option: add Fibocom NL668 variants
  USB: serial: ch341: sort device-id entries
  USB: serial: ch341: add new Product ID for CH341A
  USB: serial: kl5kusb105: fix memleak on open
  usb: gadget: f_fs: Use local copy of descriptors for userspace copy
  vlan: consolidate VLAN parsing code and limit max parsing depth
  pinctrl: baytrail: Fix pin being driven low for a while on gpiod_get(..., GPIOD_OUT_HIGH)
  pinctrl: baytrail: Replace WARN with dev_info_once when setting direct-irq pin to output
  ANDROID: Incremental fs: Set credentials before reading/writing
  ANDROID: Incremental fs: Fix incfs_test use of atol, open
  ANDROID: Incremental fs: Change per UID timeouts to microseconds
  ANDROID: Incremental fs: Add v2 feature flag
  ANDROID: Incremental fs: Add zstd feature flag
  Linux 4.14.211
  RDMA/i40iw: Address an mmap handler exploit in i40iw
  Input: i8042 - add ByteSpeed touchpad to noloop table
  Input: xpad - support Ardwiino Controllers
  ALSA: usb-audio: US16x08: fix value count for level meters
  dt-bindings: net: correct interrupt flags in examples
  net/mlx5: Fix wrong address reclaim when command interface is down
  net: pasemi: fix error return code in pasemi_mac_open()
  cxgb3: fix error return code in t3_sge_alloc_qset()
  net/x25: prevent a couple of overflows
  ibmvnic: Fix TX completion error handling
  ibmvnic: Ensure that SCRQ entry reads are correctly ordered
  ipv4: Fix tos mask in inet_rtm_getroute()
  netfilter: bridge: reset skb->pkt_type after NF_INET_POST_ROUTING traversal
  bonding: wait for sysfs kobject destruction before freeing struct slave
  usbnet: ipheth: fix connectivity with iOS 14
  tun: honor IOCB_NOWAIT flag
  tcp: Set INET_ECN_xmit configuration in tcp_reinit_congestion_control
  sock: set sk_err to ee_errno on dequeue from errq
  rose: Fix Null pointer dereference in rose_send_frame()
  net/af_iucv: set correct sk_protocol for child sockets
  ANDROID: Incremental fs: Fix 32-bit build
  UPSTREAM: arm64: sysreg: Clean up instructions for modifying PSTATE fields
  [CP] CHROMIUM: drm/virtio: rebase zero-copy patches to virgl/drm-misc-next
  Linux 4.14.210
  USB: core: Fix regression in Hercules audio card
  USB: core: add endpoint-blacklist quirk
  x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak
  x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount leak
  x86/speculation: Fix prctl() when spectre_v2_user={seccomp,prctl},ibpb
  usb: gadget: Fix memleak in gadgetfs_fill_super
  usb: gadget: f_midi: Fix memleak in f_midi_alloc
  USB: core: Change %pK for __user pointers to %px
  perf probe: Fix to die_entrypc() returns error correctly
  can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
  platform/x86: toshiba_acpi: Fix the wrong variable assignment
  can: gs_usb: fix endianess problem with candleLight firmware
  efivarfs: revert "fix memory leak in efivarfs_create()"
  ibmvnic: fix NULL pointer dereference in ibmvic_reset_crq
  ibmvnic: fix NULL pointer dereference in reset_sub_crq_queues
  net: ena: set initial DMA width to avoid intel iommu issue
  nfc: s3fwrn5: use signed integer for parsing GPIO numbers
  IB/mthca: fix return value of error branch in mthca_init_cq()
  bnxt_en: Release PCI regions when DMA mask setup fails during probe.
  video: hyperv_fb: Fix the cache type when mapping the VRAM
  bnxt_en: fix error return code in bnxt_init_board()
  bnxt_en: fix error return code in bnxt_init_one()
  scsi: ufs: Fix race between shutdown and runtime resume flow
  batman-adv: set .owner to THIS_MODULE
  phy: tegra: xusb: Fix dangling pointer on probe failure
  perf/x86: fix sysfs type mismatches
  scsi: target: iscsi: Fix cmd abort fabric stop race
  scsi: libiscsi: Fix NOP race condition
  dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size
  nvme: free sq/cq dbbuf pointers when dbbuf set fails
  proc: don't allow async path resolution of /proc/self components
  HID: Add Logitech Dinovo Edge battery quirk
  x86/xen: don't unbind uninitialized lock_kicker_irq
  dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
  HID: hid-sensor-hub: Fix issue with devices with no report ID
  Input: i8042 - allow insmod to succeed on devices without an i8042 controller
  HID: cypress: Support Varmilo Keyboards' media hotkeys
  ALSA: hda/hdmi: fix incorrect locking in hdmi_pcm_close
  ALSA: hda/hdmi: Use single mutex unlock in error paths
  arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
  arm64: pgtable: Fix pte_accessible()
  btrfs: inode: Verify inode mode to avoid NULL pointer dereference
  btrfs: adjust return values of btrfs_inode_by_name
  btrfs: tree-checker: Enhance chunk checker to validate chunk profile
  PCI: Add device even if driver attach failed
  wireless: Use linux/stddef.h instead of stddef.h
  btrfs: fix lockdep splat when reading qgroup config on mount
  mm/userfaultfd: do not access vma->vm_mm after calling handle_userfault()
  perf event: Check ref_reloc_sym before using it
  Linux 4.14.209
  x86/microcode/intel: Check patch signature before saving microcode for early loading
  s390/dasd: fix null pointer dereference for ERP requests
  s390/cpum_sf.c: fix file permission for cpum_sfb_size
  mac80211: free sta in sta_info_insert_finish() on errors
  mac80211: minstrel: fix tx status processing corner case
  mac80211: minstrel: remove deferred sampling code
  xtensa: disable preemption around cache alias management calls
  regulator: workaround self-referent regulators
  regulator: avoid resolve_supply() infinite recursion
  regulator: fix memory leak with repeated set_machine_constraints()
  iio: accel: kxcjk1013: Add support for KIOX010A ACPI DSM for setting tablet-mode
  iio: accel: kxcjk1013: Replace is_smo8500_device with an acpi_type enum
  ext4: fix bogus warning in ext4_update_dx_flag()
  staging: rtl8723bs: Add 024c:0627 to the list of SDIO device-ids
  efivarfs: fix memory leak in efivarfs_create()
  tty: serial: imx: keep console clocks always on
  ALSA: mixart: Fix mutex deadlock
  ALSA: ctl: fix error path at adding user-defined element set
  speakup: Do not let the line discipline be used several times
  powerpc/uaccess-flush: fix missing includes in kup-radix.h
  libfs: fix error cast of negative value in simple_attr_write()
  xfs: revert "xfs: fix rmap key and record comparison functions"
  regulator: ti-abb: Fix array out of bound read access on the first transition
  MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
  ASoC: qcom: lpass-platform: Fix memory leak
  can: m_can: m_can_handle_state_change(): fix state change
  can: peak_usb: fix potential integer overflow on shift of a int
  can: mcba_usb: mcba_usb_start_xmit(): first fill skb, then pass to can_put_echo_skb()
  can: ti_hecc: Fix memleak in ti_hecc_probe
  can: dev: can_restart(): post buffer from the right context
  can: af_can: prevent potential access of uninitialized member in canfd_rcv()
  can: af_can: prevent potential access of uninitialized member in can_rcv()
  perf lock: Don't free "lock_seq_stat" if read_count isn't zero
  ARM: dts: imx50-evk: Fix the chip select 1 IOMUX
  arm: dts: imx6qdl-udoo: fix rgmii phy-mode for ksz9031 phy
  MIPS: export has_transparent_hugepage() for modules
  Input: adxl34x - clean up a data type in adxl34x_probe()
  vfs: remove lockdep bogosity in __sb_start_write
  arm64: psci: Avoid printing in cpu_psci_cpu_die()
  pinctrl: rockchip: enable gpio pclk for rockchip_gpio_to_irq
  net: ftgmac100: Fix crash when removing driver
  tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
  net: usb: qmi_wwan: Set DTR quirk for MR400
  net/mlx5: Disable QoS when min_rates on all VFs are zero
  sctp: change to hold/put transport for proto_unreach_timer
  qlcnic: fix error return code in qlcnic_83xx_restart_hw()
  net: x25: Increase refcnt of "struct x25_neigh" in x25_rx_call_request
  net/mlx4_core: Fix init_hca fields offset
  netlabel: fix an uninitialized warning in netlbl_unlabel_staticlist()
  netlabel: fix our progress tracking in netlbl_unlabel_staticlist()
  net: Have netpoll bring-up DSA management interface
  net: dsa: mv88e6xxx: Avoid VTU corruption on 6097
  net: bridge: add missing counters to ndo_get_stats64 callback
  net: b44: fix error return code in b44_init_one()
  mlxsw: core: Use variable timeout for EMAD retries
  inet_diag: Fix error path to cancel the meseage in inet_req_diag_fill()
  devlink: Add missing genlmsg_cancel() in devlink_nl_sb_port_pool_fill()
  bnxt_en: read EEPROM A2h address using page 0
  atm: nicstar: Unmap DMA on send error
  ah6: fix error return code in ah6_input()
  ANDROID: Fix cuttlefish defconfigs now incfs uses zstd
  ANDROID: Incremental fs: Add zstd compression support
  ANDROID: Incremental fs: Small improvements
  ANDROID: Incremental fs: Initialize mount options correctly
  ANDROID: Incremental fs: Fix read_log_test which failed sporadically
  ANDROID: Incremental fs: Fix misuse of cpu_to_leXX and poll return
  ANDROID: Incremental fs: Add per UID read timeouts
  ANDROID: Incremental fs: Add .incomplete folder
  ANDROID: Incremental fs: Fix dangling else
  ANDROID: Incremental fs: Fix uninitialized variable
  ANDROID: Incremental fs: Fix filled block count from get filled blocks
  ANDROID: Incremental fs: Add hash block counts to IOC_IOCTL_GET_BLOCK_COUNT
  ANDROID: Incremental fs: Add INCFS_IOC_GET_BLOCK_COUNT
  ANDROID: Incremental fs: Make compatible with existing files
  ANDROID: Incremental fs: Remove block HASH flag
  ANDROID: Incremental fs: Remove back links and crcs
  ANDROID: Incremental fs: Remove attributes from file
  ANDROID: Incremental fs: Add .blocks_written file
  ANDROID: Incremental fs: Separate pseudo-file code
  ANDROID: Incremental fs: Add UID to pending_read
  ANDROID: Incremental fs: Create mapped file
  ANDROID: Incremental fs: Don't allow renaming .index directory.
  ANDROID: Incremental fs: Fix incfs to work on virtio-9p
  ANDROID: Incremental fs: Allow running a single test
  ANDROID: Incremental fs: Adding perf test
  ANDROID: Incremental fs: Stress tool
  ANDROID: Incremental fs: Use R/W locks to read/write segment blockmap.
  ANDROID: Incremental fs: Remove unnecessary dependencies
  ANDROID: Incremental fs: Remove annoying pr_debugs
  ANDROID: Incremental fs: dentry_revalidate should not return -EBADF.
  ANDROID: Incremental fs: Fix minor bugs
  ANDROID: Incremental fs: RCU locks instead of mutex for pending_reads.
  ANDROID: Incremental fs: fix up attempt to copy structures with READ/WRITE_ONCE
  Linux 4.14.208
  ACPI: GED: fix -Wformat
  KVM: x86: clflushopt should be treated as a no-op by emulation
  can: proc: can_remove_proc(): silence remove_proc_entry warning
  mac80211: always wind down STA state
  Input: sunkbd - avoid use-after-free in teardown paths
  powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
  gpio: mockup: fix resource leak in error path
  i2c: imx: Fix external abort on interrupt in exit paths
  i2c: imx: use clk notifier for rate changes
  powerpc/64s: flush L1D after user accesses
  powerpc/uaccess: Evaluate macro arguments once, before user access is allowed
  powerpc: Fix __clear_user() with KUAP enabled
  powerpc: Implement user_access_begin and friends
  powerpc: Add a framework for user access tracking
  powerpc/64s: flush L1D on kernel entry
  powerpc/64s: move some exception handlers out of line
  powerpc/64s: Define MASKABLE_RELON_EXCEPTION_PSERIES_OOL
  Linux 4.14.207
  mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
  Convert trailing spaces and periods in path components
  reboot: fix overflow parsing reboot cpu number
  Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
  perf/core: Fix race in the perf_mmap_close() function
  xen/events: block rogue events for some time
  xen/events: defer eoi in case of excessive number of events
  xen/events: use a common cpu hotplug hook for event channels
  xen/events: switch user event channels to lateeoi model
  xen/pciback: use lateeoi irq binding
  xen/pvcallsback: use lateeoi irq binding
  xen/scsiback: use lateeoi irq binding
  xen/netback: use lateeoi irq binding
  xen/blkback: use lateeoi irq binding
  xen/events: add a new "late EOI" evtchn framework
  xen/events: fix race in evtchn_fifo_unmask()
  xen/events: add a proper barrier to 2-level uevent unmasking
  xen/events: avoid removing an event channel while handling it
  perf/core: Fix a memory leak in perf_event_parse_addr_filter()
  perf/core: Fix crash when using HW tracing kernel filters
  perf/core: Fix bad use of igrab()
  x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP
  random32: make prandom_u32() output unpredictable
  net: Update window_clamp if SOCK_RCVBUF is set
  r8169: fix potential skb double free in an error path
  vrf: Fix fast path output packet handling with async Netfilter rules
  net/x25: Fix null-ptr-deref in x25_connect
  net/af_iucv: fix null pointer dereference on shutdown
  IPv6: Set SIT tunnel hard_header_len to zero
  swiotlb: fix "x86: Don't panic if can not alloc buffer for swiotlb"
  pinctrl: amd: fix incorrect way to disable debounce filter
  pinctrl: amd: use higher precision for 512 RtcClk
  drm/gma500: Fix out-of-bounds access to struct drm_device.vblank[]
  don't dump the threads that had been already exiting when zapped.
  selinux: Fix error return code in sel_ib_pkey_sid_slow()
  ocfs2: initialize ip_next_orphan
  futex: Don't enable IRQs unconditionally in put_pi_state()
  mei: protect mei_cl_mtu from null dereference
  usb: cdc-acm: Add DISABLE_ECHO for Renesas USB Download mode
  uio: Fix use-after-free in uio_unregister_device()
  thunderbolt: Add the missed ida_simple_remove() in ring_request_msix()
  ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
  ext4: correctly report "not supported" for {usr,grp}jquota when !CONFIG_QUOTA
  perf: Fix get_recursion_context()
  cosa: Add missing kfree in error path of cosa_write
  of/address: Fix of_node memory leak in of_dma_is_coherent
  xfs: fix a missing unlock on error in xfs_fs_map_blocks
  xfs: fix rmap key and record comparison functions
  xfs: fix flags argument to rmap lookup when converting shared file rmaps
  nbd: fix a block_device refcount leak in nbd_release
  pinctrl: aspeed: Fix GPI only function problem.
  ARM: 9019/1: kprobes: Avoid fortify_panic() when copying optprobe template
  pinctrl: intel: Set default bias in case no particular value given
  iommu/amd: Increase interrupt remapping table limit to 512 entries
  scsi: scsi_dh_alua: Avoid crash during alua_bus_detach()
  cfg80211: regulatory: Fix inconsistent format argument
  mac80211: fix use of skb payload instead of header
  drm/amdgpu: perform srbm soft reset always on SDMA resume
  scsi: hpsa: Fix memory leak in hpsa_init_one()
  gfs2: check for live vs. read-only file system in gfs2_fitrim
  gfs2: Add missing truncate_inode_pages_final for sd_aspace
  gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
  usb: gadget: goku_udc: fix potential crashes in probe
  ath9k_htc: Use appropriate rs_datalen type
  Btrfs: fix missing error return if writeback for extent buffer never started
  xfs: flush new eof page on truncate to avoid post-eof corruption
  can: peak_canfd: pucan_handle_can_rx(): fix echo management when loopback is on
  can: peak_usb: peak_usb_get_ts_time(): fix timestamp wrapping
  can: peak_usb: add range checking in decode operations
  can: can_create_echo_skb(): fix echo skb generation: always use skb_clone()
  can: dev: __can_get_echo_skb(): fix real payload length return value for RTR frames
  can: dev: can_get_echo_skb(): prevent call to kfree_skb() in hard IRQ context
  can: rx-offload: don't call kfree_skb() from IRQ context
  ALSA: hda: prevent undefined shift in snd_hdac_ext_bus_get_link()
  perf tools: Add missing swap for ino_generation
  net: xfrm: fix a race condition during allocing spi
  hv_balloon: disable warning when floor reached
  genirq: Let GENERIC_IRQ_IPI select IRQ_DOMAIN_HIERARCHY
  btrfs: reschedule when cloning lots of extents
  btrfs: sysfs: init devices outside of the chunk_mutex
  nbd: don't update block size after device is started
  time: Prevent undefined behaviour in timespec64_to_ns()
  mm: mempolicy: fix potential pte_unmap_unlock pte error
  ring-buffer: Fix recursion protection transitions between interrupt context
  regulator: defer probe when trying to get voltage from unresolved supply
  UPSTREAM: sched: idle: Avoid retaining the tick when it has been stopped
  UPSTREAM: cpuidle: menu: Handle stopped tick more aggressively
  UPSTREAM: staging: android: vsoc: fix copy_from_user overrun
  UPSTREAM: ipv6: ndisc: RFC-ietf-6man-ra-pref64-09 is now published as RFC8781
  BACKPORT: drm/virtio: fix missing dma_fence_put() in virtio_gpu_execbuffer_ioctl()
  Linux 4.14.206
  powercap: restrict energy meter to root access
  Linux 4.14.205
  arm64: dts: marvell: espressobin: add ethernet alias
  PM: runtime: Resume the device earlier in __device_release_driver()
  Revert "ARC: entry: fix potential EFA clobber when TIF_SYSCALL_TRACE"
  ARC: stack unwinding: avoid indefinite looping
  usb: mtu3: fix panic in mtu3_gadget_stop()
  USB: Add NO_LPM quirk for Kingston flash drive
  USB: serial: option: add Telit FN980 composition 0x1055
  USB: serial: option: add LE910Cx compositions 0x1203, 0x1230, 0x1231
  USB: serial: option: add Quectel EC200T module support
  USB: serial: cyberjack: fix write-URB completion race
  serial: txx9: add missing platform_driver_unregister() on error in serial_txx9_init
  serial: 8250_mtk: Fix uart_get_baud_rate warning
  fork: fix copy_process(CLONE_PARENT) race with the exiting ->real_parent
  vt: Disable KD_FONT_OP_COPY
  ACPI: NFIT: Fix comparison to '-ENXIO'
  drm/vc4: drv: Add error handding for bind
  vsock: use ns_capable_noaudit() on socket create
  scsi: core: Don't start concurrent async scan on same host
  blk-cgroup: Pre-allocate tree node on blkg_conf_prep
  blk-cgroup: Fix memleak on error path
  of: Fix reserved-memory overlap detection
  x86/kexec: Use up-to-dated screen_info copy to fill boot params
  ARM: dts: sun4i-a10: fix cpu_alert temperature
  futex: Handle transient "ownerless" rtmutex state correctly
  tracing: Fix out of bounds write in get_trace_buf
  ftrace: Handle tracing when switching between context
  ftrace: Fix recursion check for NMI test
  gfs2: Wake up when sd_glock_disposal becomes zero
  mm: always have io_remap_pfn_range() set pgprot_decrypted()
  kthread_worker: prevent queuing delayed work from timer_fn when it is being canceled
  lib/crc32test: remove extra local_irq_disable/enable
  ALSA: usb-audio: Add implicit feedback quirk for Qu-16
  Fonts: Replace discarded const qualifier
  i40e: Memory leak in i40e_config_iwarp_qvlist
  i40e: Fix of memory leak and integer truncation in i40e_virtchnl.c
  i40e: Wrong truncation from u16 to u8
  i40e: add num_vectors checker in iwarp handler
  i40e: Fix a potential NULL pointer dereference
  blktrace: fix debugfs use after free
  Blktrace: bail out early if block debugfs is not configured
  sfp: Fix error handing in sfp_probe()
  sctp: Fix COMM_LOST/CANT_STR_ASSOC err reporting on big-endian platforms
  net: usb: qmi_wwan: add Telit LE910Cx 0x1230 composition
  gianfar: Account for Tx PTP timestamp in the skb headroom
  gianfar: Replace skb_realloc_headroom with skb_cow_head for PTP
  tipc: fix use-after-free in tipc_bcast_get_mode
  xen/events: don't use chip_data for legacy IRQs
  drm/i915: Break up error capture compression loops with cond_resched()
  ANDROID: Temporarily disable XFRM_USER_COMPAT filtering
  Linux 4.14.204
  staging: octeon: Drop on uncorrectable alignment or FCS error
  staging: octeon: repair "fixed-link" support
  staging: comedi: cb_pcidas: Allow 2-channel commands for AO subdevice
  KVM: arm64: Fix AArch32 handling of DBGD{CCINT,SCRext} and DBGVCR
  device property: Don't clear secondary pointer for shared primary firmware node
  device property: Keep secondary firmware node secondary by type
  ARM: s3c24xx: fix missing system reset
  ARM: samsung: fix PM debug build with DEBUG_LL but !MMU
  arm: dts: mt7623: add missing pause for switchport
  hil/parisc: Disable HIL driver when it gets stuck
  cachefiles: Handle readpage error correctly
  arm64: berlin: Select DW_APB_TIMER_OF
  tty: make FONTX ioctl use the tty pointer they were actually passed
  rtc: rx8010: don't modify the global rtc ops
  drm/ttm: fix eviction valuable range check.
  ext4: fix invalid inode checksum
  ext4: fix error handling code in add_new_gdb
  ext4: fix leaking sysfs kobject after failed mount
  vringh: fix __vringh_iov() when riov and wiov are different
  ring-buffer: Return 0 on success from ring_buffer_resize()
  9P: Cast to loff_t before multiplying
  libceph: clear con->out_msg on Policy::stateful_server faults
  ceph: promote to unsigned long long before shifting
  drm/amdgpu: don't map BO in reserved region
  ia64: fix build error with !COREDUMP
  ubi: check kthread_should_stop() after the setting of task state
  perf python scripting: Fix printable strings in python3 scripts
  ubifs: dent: Fix some potential memory leaks while iterating entries
  NFSD: Add missing NFSv2 .pc_func methods
  NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
  powerpc/powernv/elog: Fix race while processing OPAL error log event.
  powerpc: Warn about use of smt_snooze_delay
  powerpc/rtas: Restrict RTAS requests from userspace
  s390/stp: add locking to sysfs functions
  iio:gyro:itg3200: Fix timestamp alignment and prevent data leak.
  iio:adc:ti-adc12138 Fix alignment issue with timestamp
  iio:adc:ti-adc0832 Fix alignment issue with timestamp
  iio:light:si1145: Fix timestamp alignment and prevent data leak.
  dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
  vt: keyboard, extend func_buf_lock to readers
  vt: keyboard, simplify vt_kdgkbsent
  drm/i915: Force VT'd workarounds when running as a guest OS
  usb: host: fsl-mph-dr-of: check return of dma_set_mask()
  usb: cdc-acm: fix cooldown mechanism
  usb: dwc3: core: don't trigger runtime pm when remove driver
  usb: dwc3: core: add phy cleanup for probe error handling
  usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
  btrfs: fix use-after-free on readahead extent after failure to create it
  btrfs: cleanup cow block on error
  btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
  btrfs: send, recompute reference path after orphanization of a directory
  btrfs: reschedule if necessary when logging directory items
  scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
  w1: mxc_w1: Fix timeout resolution problem leading to bus error
  acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
  ACPI: debug: don't allow debugging when ACPI is disabled
  ACPI: video: use ACPI backlight for HP 635 Notebook
  ACPI / extlog: Check for RDMSR failure
  NFS: fix nfs_path in case of a rename retry
  fs: Don't invalidate page buffers in block_write_full_page()
  leds: bcm6328, bcm6358: use devres LED registering function
  perf/x86/amd/ibs: Fix raw sample data accumulation
  perf/x86/amd/ibs: Don't include randomized bits in get_ibs_op_count()
  md/raid5: fix oops during stripe resizing
  nvme-rdma: fix crash when connect rejected
  sgl_alloc_order: fix memory leak
  nbd: make the config put is called before the notifying the waiter
  ARM: dts: s5pv210: remove dedicated 'audio-subsystem' node
  ARM: dts: s5pv210: move PMU node out of clock controller
  ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema warnings
  memory: emif: Remove bogus debugfs error handling
  arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC nodes
  gfs2: add validation checks for size of superblock
  ext4: Detect already used quota file early
  drivers: watchdog: rdc321x_wdt: Fix race condition bugs
  net: 9p: initialize sun_server.sun_path to have addr's value only when addr is valid
  clk: ti: clockdomain: fix static checker warning
  bnxt_en: Log unknown link speed appropriately.
  md/bitmap: md_bitmap_get_counter returns wrong blocks
  power: supply: test_power: add missing newlines when printing parameters by sysfs
  bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
  drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
  ACPI: Add out of bounds and numa_off protections to pxm_to_node()
  arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
  uio: free uio id after uio file node is freed
  USB: adutux: fix debugging
  cpufreq: sti-cpufreq: add stih418 support
  kgdb: Make "kgdbcon" work properly with "kgdb_earlycon"
  printk: reduce LOG_BUF_SHIFT range for H8300
  drm/bridge/synopsys: dsi: add support for non-continuous HS clock
  mmc: via-sdmmc: Fix data race bug
  media: tw5864: check status of tw5864_frameinterval_get
  usb: typec: tcpm: During PR_SWAP, source caps should be sent only after tSwapSourceStart
  media: platform: Improve queue set up flow for bug fixing
  media: videodev2.h: RGB BT2020 and HSV are always full range
  drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working correctly
  ath10k: fix VHT NSS calculation when STBC is enabled
  ath10k: start recovery process when payload length exceeds max htc length for sdio
  video: fbdev: pvr2fb: initialize variables
  xfs: fix realtime bitmap/summary file truncation when growing rt volume
  ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses
  um: change sigio_spinlock to a mutex
  f2fs: fix to check segment boundary during SIT page readahead
  f2fs: add trace exit in exception path
  sparc64: remove mm_cpumask clearing to fix kthread_use_mm race
  powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
  powerpc/powernv/smp: Fix spurious DBG() warning
  futex: Fix incorrect should_fail_futex() handling
  mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
  x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10 compiled kernels
  fscrypt: return -EXDEV for incompatible rename or link into encrypted dir
  ata: sata_rcar: Fix DMA boundary mask
  mtd: lpddr: Fix bad logic in print_drs_error
  p54: avoid accessing the data mapped to streaming DMA
  fuse: fix page dereference after free
  x86/xen: disable Firmware First mode for correctable memory errors
  arch/x86/amd/ibs: Fix re-arming IBS Fetch
  tipc: fix memory leak caused by tipc_buf_append()
  ravb: Fix bit fields checking in ravb_hwtstamp_get()
  gtp: fix an use-before-init in gtp_newlink()
  efivarfs: Replace invalid slashes with exclamation marks in dentries.
  arm64: link with -z norelro regardless of CONFIG_RELOCATABLE
  scripts/setlocalversion: make git describe output more reliable
  UPSTREAM: mm/sl[uo]b: export __kmalloc_track(_node)_caller
  BACKPORT: xfrm/compat: Translate 32-bit user_policy from sockptr
  BACKPORT: xfrm/compat: Add 32=>64-bit messages translator
  UPSTREAM: xfrm/compat: Attach xfrm dumps to 64=>32 bit translator
  UPSTREAM: xfrm/compat: Add 64=>32-bit messages translator
  BACKPORT: xfrm: Provide API to register translator module
  ANDROID: Publish uncompressed Image on aarch64
  Linux 4.14.203
  powerpc/powernv/opal-dump : Use IRQ_HANDLED instead of numbers in interrupt handler
  usb: gadget: f_ncm: allow using NCM in SuperSpeed Plus gadgets.
  eeprom: at25: set minimum read/write access stride to 1
  USB: cdc-wdm: Make wdm_flush() interruptible and add wdm_fsync().
  usb: cdc-acm: add quirk to blacklist ETAS ES58X devices
  tty: serial: fsl_lpuart: fix lpuart32_poll_get_char
  net: korina: cast KSEG0 address to pointer in kfree
  ath10k: check idx validity in __ath10k_htt_rx_ring_fill_n()
  scsi: ufs: ufs-qcom: Fix race conditions caused by ufs_qcom_testbus_config()
  usb: core: Solve race condition in anchor cleanup functions
  brcm80211: fix possible memleak in brcmf_proto_msgbuf_attach
  mwifiex: don't call del_timer_sync() on uninitialized timer
  reiserfs: Fix memory leak in reiserfs_parse_options()
  ipvs: Fix uninit-value in do_ip_vs_set_ctl()
  tty: ipwireless: fix error handling
  scsi: qedi: Fix list_del corruption while removing active I/O
  scsi: qedi: Protect active command list to avoid list corruption
  Fix use after free in get_capset_info callback.
  rtl8xxxu: prevent potential memory leak
  brcmsmac: fix memory leak in wlc_phy_attach_lcnphy
  scsi: ibmvfc: Fix error return in ibmvfc_probe()
  Bluetooth: Only mark socket zapped after unlocking
  usb: ohci: Default to per-port over-current protection
  xfs: make sure the rt allocator doesn't run off the end
  reiserfs: only call unlock_new_inode() if I_NEW
  misc: rtsx: Fix memory leak in rtsx_pci_probe
  ath9k: hif_usb: fix race condition between usb_get_urb() and usb_kill_anchored_urbs()
  can: flexcan: flexcan_chip_stop(): add error handling and propagate error value
  USB: cdc-acm: handle broken union descriptors
  udf: Avoid accessing uninitialized data on failed inode read
  udf: Limit sparing table size
  usb: gadget: function: printer: fix use-after-free in __lock_acquire
  misc: vop: add round_up(x,4) for vring_size to avoid kernel panic
  mic: vop: copy data to kernel space then write to io memory
  scsi: target: core: Add CONTROL field for trace events
  scsi: mvumi: Fix error return in mvumi_io_attach()
  PM: hibernate: remove the bogus call to get_gendisk() in software_resume()
  mac80211: handle lack of sband->bitrates in rates
  ntfs: add check for mft record size in superblock
  media: venus: core: Fix runtime PM imbalance in venus_probe
  fs: dlm: fix configfs memory leak
  media: saa7134: avoid a shift overflow
  mmc: sdio: Check for CISTPL_VERS_1 buffer size
  media: uvcvideo: Ensure all probed info is returned to v4l2
  media: media/pci: prevent memory leak in bttv_probe
  media: bdisp: Fix runtime PM imbalance on error
  media: platform: sti: hva: Fix runtime PM imbalance on error
  media: platform: s3c-camif: Fix runtime PM imbalance on error
  media: vsp1: Fix runtime PM imbalance on error
  media: exynos4-is: Fix a reference count leak
  media: exynos4-is: Fix a reference count leak due to pm_runtime_get_sync
  media: exynos4-is: Fix several reference count leaks due to pm_runtime_get_sync
  media: sti: Fix reference count leaks
  media: st-delta: Fix reference count leak in delta_run_work
  media: ati_remote: sanity check for both endpoints
  media: firewire: fix memory leak
  crypto: ccp - fix error handling
  i2c: core: Restore acpi_walk_dep_device_list() getting called after registering the ACPI i2c devs
  perf: correct SNOOPX field offset
  NTB: hw: amd: fix an issue about leak system resources
  nvmet: fix uninitialized work for zero kato
  powerpc/powernv/dump: Fix race while processing OPAL dump
  arm64: dts: zynqmp: Remove additional compatible string for i2c IPs
  ARM: dts: owl-s500: Fix incorrect PPI interrupt specifiers
  arm64: dts: qcom: msm8916: Fix MDP/DSI interrupts
  memory: fsl-corenet-cf: Fix handling of platform_get_irq() error
  memory: omap-gpmc: Fix a couple off by ones
  KVM: x86: emulating RDPID failure shall return #UD rather than #GP
  Input: sun4i-ps2 - fix handling of platform_get_irq() error
  Input: twl4030_keypad - fix handling of platform_get_irq() error
  Input: omap4-keypad - fix handling of platform_get_irq() error
  Input: ep93xx_keypad - fix handling of platform_get_irq() error
  Input: stmfts - fix a & vs && typo
  Input: imx6ul_tsc - clean up some errors in imx6ul_tsc_resume()
  vfio iommu type1: Fix memory leak in vfio_iommu_type1_pin_pages
  vfio/pci: Clear token on bypass registration failure
  ext4: limit entries returned when counting fsmap records
  clk: bcm2835: add missing release if devm_clk_hw_register fails
  clk: at91: clk-main: update key before writing AT91_CKGR_MOR
  PCI: iproc: Set affinity mask on MSI interrupts
  i2c: rcar: Auto select RESET_CONTROLLER
  mailbox: avoid timer start from callback
  rapidio: fix the missed put_device() for rio_mport_add_riodev
  rapidio: fix error handling path
  ramfs: fix nommu mmap with gaps in the page cache
  lib/crc32.c: fix trivial typo in preprocessor condition
  f2fs: wait for sysfs kobject removal before freeing f2fs_sb_info
  IB/rdmavt: Fix sizeof mismatch
  cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier
  powerpc/perf/hv-gpci: Fix starting index value
  powerpc/perf: Exclude pmc5/6 from the irrelevant PMU group constraints
  overflow: Include header file with SIZE_MAX declaration
  kdb: Fix pager search for multi-line strings
  RDMA/hns: Set the unsupported wr opcode
  perf intel-pt: Fix "context_switch event has no tid" error
  powerpc/tau: Disable TAU between measurements
  powerpc/tau: Remove duplicated set_thresholds() call
  powerpc/tau: Use appropriate temperature sample interval
  RDMA/qedr: Fix use of uninitialized field
  xfs: limit entries returned when counting fsmap records
  arc: plat-hsdk: fix kconfig dependency warning when !RESET_CONTROLLER
  ARM: 9007/1: l2c: fix prefetch bits init in L2X0_AUX_CTRL using DT values
  mtd: mtdoops: Don't write panic data twice
  mtd: lpddr: fix excessive stack usage with clang
  powerpc/icp-hv: Fix missing of_node_put() in success path
  powerpc/pseries: Fix missing of_node_put() in rng_init()
  IB/mlx4: Adjust delayed work when a dup is observed
  IB/mlx4: Fix starvation in paravirt mux/demux
  mm, oom_adj: don't loop through tasks in __set_oom_adj when not necessary
  mm/memcg: fix device private memcg accounting
  net: korina: fix kfree of rx/tx descriptor array
  mwifiex: fix double free
  scsi: be2iscsi: Fix a theoretical leak in beiscsi_create_eqs()
  usb: dwc2: Fix INTR OUT transfers in DDMA mode.
  nl80211: fix non-split wiphy information
  usb: gadget: u_ether: enable qmult on SuperSpeed Plus as well
  usb: gadget: f_ncm: fix ncm_bitrate for SuperSpeed and above.
  iwlwifi: mvm: split a print to avoid a WARNING in ROC
  mfd: sm501: Fix leaks in probe()
  net: enic: Cure the enic api locking trainwreck
  qtnfmac: fix resource leaks on unsupported iftype error return path
  HID: hid-input: fix stylus battery reporting
  quota: clear padding in v2r1_mem2diskdqb()
  usb: dwc2: Fix parameter type in function pointer prototype
  ALSA: seq: oss: Avoid mutex lock for a long-time ioctl
  misc: mic: scif: Fix error handling path
  ath6kl: wmi: prevent a shift wrapping bug in ath6kl_wmi_delete_pstream_cmd()
  pinctrl: mcp23s08: Fix mcp23x17 precious range
  pinctrl: mcp23s08: Fix mcp23x17_regmap initialiser
  HID: roccat: add bounds checking in kone_sysfs_write_settings()
  video: fbdev: sis: fix null ptr dereference
  video: fbdev: vga16fb: fix setting of pixclock because a pass-by-value error
  drivers/virt/fsl_hypervisor: Fix error handling path
  pwm: lpss: Add range limit check for the base_unit register value
  pwm: lpss: Fix off by one error in base_unit math in pwm_lpss_prepare()
  pty: do tty_flip_buffer_push without port->lock in pty_write
  tty: hvcs: Don't NULL tty->driver_data until hvcs_cleanup()
  tty: serial: earlycon dependency
  VMCI: check return value of get_user_pages_fast() for errors
  backlight: sky81452-backlight: Fix refcount imbalance on error
  scsi: csiostor: Fix wrong return value in csio_hw_prep_fw()
  scsi: qla4xxx: Fix an error handling path in 'qla4xxx_get_host_stats()'
  drm/gma500: fix error check
  mwifiex: Do not use GFP_KERNEL in atomic context
  brcmfmac: check ndev pointer
  ASoC: qcom: lpass-cpu: fix concurrency issue
  ASoC: qcom: lpass-platform: fix memory leak
  wcn36xx: Fix reported 802.11n rx_highest rate wcn3660/wcn3680
  ath9k: Fix potential out of bounds in ath9k_htc_txcompletion_cb()
  ath6kl: prevent potential array overflow in ath6kl_add_new_sta()
  Bluetooth: hci_uart: Cancel init work before unregistering
  ath10k: provide survey info as accumulated data
  regulator: resolve supply after creating regulator
  media: ti-vpe: Fix a missing check and reference count leak
  media: s5p-mfc: Fix a reference count leak
  media: platform: fcp: Fix a reference count leak.
  media: tc358743: initialize variable
  media: mx2_emmaprp: Fix memleak in emmaprp_probe
  cypto: mediatek - fix leaks in mtk_desc_ring_alloc
  crypto: omap-sham - fix digcnt register handling with export/import
  media: omap3isp: Fix memleak in isp_probe
  media: uvcvideo: Set media controller entity functions
  media: m5mols: Check function pointer in m5mols_sensor_power
  media: Revert "media: exynos4-is: Add missed check for pinctrl_lookup_state()"
  media: tuner-simple: fix regression in simple_set_radio_freq
  crypto: ixp4xx - Fix the size used in a 'dma_free_coherent()' call
  crypto: mediatek - Fix wrong return value in mtk_desc_ring_alloc()
  crypto: algif_skcipher - EBUSY on aio should be an error
  drivers/perf: xgene_pmu: Fix uninitialized resource struct
  x86/fpu: Allow multiple bits in clearcpuid= parameter
  EDAC/i5100: Fix error handling order in i5100_init_one()
  crypto: algif_aead - Do not set MAY_BACKLOG on the async path
  ima: Don't ignore errors from crypto_shash_update()
  KVM: SVM: Initialize prev_ga_tag before use
  KVM: x86/mmu: Commit zap of remaining invalid pages when recovering lpages
  cifs: Return the error from crypt_message when enc/dec key not found.
  cifs: remove bogus debug code
  icmp: randomize the global rate limiter
  tcp: fix to update snd_wl1 in bulk receiver fast path
  nfc: Ensure presence of NFC_ATTR_FIRMWARE_NAME attribute in nfc_genl_fw_download()
  net: hdlc_raw_eth: Clear the IFF_TX_SKB_SHARING flag after calling ether_setup
  net: hdlc: In hdlc_rcv, check to make sure dev is an HDLC device
  ALSA: bebob: potential info leak in hwdep_read()
  binder: fix UAF when releasing todo list
  r8169: fix data corruption issue on RTL8402
  net/ipv4: always honour route mtu during forwarding
  tipc: fix the skb_unshare() in tipc_buf_append()
  net: usb: qmi_wwan: add Cellient MPL200 card
  mlx4: handle non-napi callers to napi_poll
  ipv4: Restore flowi4_oif update before call to xfrm_lookup_route
  ibmveth: Identify ingress large send packets.
  ibmveth: Switch order of ibmveth_helper calls.
  ANDROID: GKI: Enable CONFIG_X86_X2APIC
  UPSTREAM: binder: fix UAF when releasing todo list
  Linux 4.14.202
  crypto: qat - check cipher length for aead AES-CBC-HMAC-SHA
  crypto: bcm - Verify GCM/CCM key length in setkey
  drivers/net/ethernet/marvell/mvmdio.c: Fix non OF case
  reiserfs: Fix oops during mount
  reiserfs: Initialize inode keys properly
  USB: serial: ftdi_sio: add support for FreeCalypso JTAG+UART adapters
  USB: serial: pl2303: add device-id for HP GC device
  staging: comedi: check validity of wMaxPacketSize of usb endpoints found
  USB: serial: option: Add Telit FT980-KS composition
  USB: serial: option: add Cellient MPL200 card
  media: usbtv: Fix refcounting mixup
  Bluetooth: Disconnect if E0 is used for Level 4
  Bluetooth: Fix update of connection state in `hci_encrypt_cfm`
  Bluetooth: Consolidate encryption handling in hci_encrypt_cfm
  Bluetooth: MGMT: Fix not checking if BT_HS is enabled
  Bluetooth: L2CAP: Fix calling sk_filter on non-socket based channel
  Bluetooth: A2MP: Fix not initializing all members
  Bluetooth: fix kernel oops in store_pending_adv_report
  ANDROID: drop KERNEL_DIR setting in build.config.common
  Linux 4.14.201
  net: usb: rtl8150: set random MAC address when set_ethernet_addr() fails
  mm: khugepaged: recalculate min_free_kbytes after memory hotplug as expected by khugepaged
  mmc: core: don't set limits.discard_granularity as 0
  perf: Fix task_function_call() error handling
  rxrpc: Fix server keyring leak
  rxrpc: Fix some missing _bh annotations on locking conn->state_lock
  rxrpc: Downgrade the BUG() for unsupported token type in rxrpc_read()
  rxrpc: Fix rxkad token xdr encoding
  net: usb: ax88179_178a: fix missing stop entry in driver_info
  mdio: fix mdio-thunder.c dependency & build error
  bonding: set dev->needed_headroom in bond_setup_by_slave()
  xfrm: Use correct address family in xfrm_state_find
  platform/x86: fix kconfig dependency warning for FUJITSU_LAPTOP
  net: stmmac: removed enabling eee in EEE set callback
  xfrm: clone whole liftime_cur structure in xfrm_do_migrate
  xfrm: clone XFRMA_SEC_CTX in xfrm_do_migrate
  xfrm: clone XFRMA_REPLAY_ESN_VAL in xfrm_do_migrate
  drm/amdgpu: prevent double kfree ttm->sg
  openvswitch: handle DNAT tuple collision
  net: team: fix memory leak in __team_options_register
  team: set dev->needed_headroom in team_setup_by_port()
  sctp: fix sctp_auth_init_hmacs() error path
  i2c: meson: fix clock setting overwrite
  cifs: Fix incomplete memory allocation on setxattr path
  mm/khugepaged: fix filemap page_to_pgoff(page) != offset
  macsec: avoid use-after-free in macsec_handle_frame()
  ftrace: Move RCU is watching check after recursion check
  Btrfs: fix unexpected failure of nocow buffered writes after snapshotting when low on space
  mtd: rawnand: sunxi: Fix the probe error path
  perf top: Fix stdio interface input handling with glibc 2.28+
  driver core: Fix probe_count imbalance in really_probe()
  platform/x86: thinkpad_acpi: re-initialize ACPI buffer size when reuse
  platform/x86: thinkpad_acpi: initialize tp_nvram_state variable
  usermodehelper: reset umask to default before executing user process
  net: wireless: nl80211: fix out-of-bounds access in nl80211_del_key()
  fbcon: Fix global-out-of-bounds read in fbcon_get_font()
  Revert "ravb: Fixed to be able to unload modules"
  Fonts: Support FONT_EXTRA_WORDS macros for built-in fonts
  fbdev, newport_con: Move FONT_EXTRA_WORDS macros into linux/font.h
  drm/syncobj: Fix drm_syncobj_handle_to_fd refcount leak
  netfilter: ctnetlink: add a range check for l3/l4 protonum
  ep_create_wakeup_source(): dentry name can change under you...
  epoll: EPOLL_CTL_ADD: close the race in decision to take fast path
  epoll: replace ->visited/visited_list with generation count
  epoll: do not insert into poll queues until all sanity checks are done
  net/packet: fix overflow in tpacket_rcv
  random32: Restore __latent_entropy attribute on net_rand_state
  Input: trackpoint - enable Synaptics trackpoints
  i2c: cpm: Fix i2c_ram structure
  iommu/exynos: add missing put_device() call in exynos_iommu_of_xlate()
  clk: samsung: exynos4: mark 'chipid' clock as CLK_IGNORE_UNUSED
  nfs: Fix security label length not being reset
  pinctrl: mvebu: Fix i2c sda definition for 98DX3236
  nvme-fc: fail new connections to a deleted host or remote port
  spi: fsl-espi: Only process interrupts for expected events
  mac80211: do not allow bigger VHT MPDUs than the hardware supports
  drivers/net/wan/hdlc: Set skb->protocol before transmitting
  drivers/net/wan/lapbether: Make skb->protocol consistent with the header
  rndis_host: increase sleep time in the query-response loop
  net: dec: de2104x: Increase receive ring size for Tulip
  drm/sun4i: mixer: Extend regmap max_register
  drivers/net/wan/hdlc_fr: Add needed_headroom for PVC devices
  drm/amdgpu: restore proper ref count in amdgpu_display_crtc_set_config
  Input: i8042 - add nopnp quirk for Acer Aspire 5 A515
  gpio: tc35894: fix up tc35894 interrupt configuration
  USB: gadget: f_ncm: Fix NDP16 datagram validation
  net: virtio_vsock: Enhance connection semantics
  vsock/virtio: add transport parameter to the virtio_transport_reset_no_sock()
  vsock/virtio: stop workers during the .remove()
  vsock/virtio: use RCU to avoid use-after-free on the_virtio_vsock
  Linux 4.14.200
  ata: sata_mv, avoid trigerrable BUG_ON
  ata: make qc_prep return ata_completion_errors
  ata: define AC_ERR_OK
  lib/string.c: implement stpcpy
  mm, THP, swap: fix allocating cluster for swapfile by mistake
  kprobes: Fix to check probe enabled before disarm_kprobe_ftrace()
  s390/dasd: Fix zero write for FBA devices
  MIPS: Add the missing 'CPU_1074K' into __get_cpu_type()
  ALSA: asihpi: fix iounmap in error handler
  batman-adv: mcast: fix duplicate mcast packets in BLA backbone from mesh
  batman-adv: Add missing include for in_interrupt()
  net: qed: RDMA personality shouldn't fail VF load
  drm/vc4/vc4_hdmi: fill ASoC card owner
  mac802154: tx: fix use-after-free
  batman-adv: mcast/TT: fix wrongly dropped or rerouted packets
  atm: eni: fix the missed pci_disable_device() for eni_init_one()
  batman-adv: bla: fix type misuse for backbone_gw hash indexing
  mwifiex: Increase AES key storage size to 256 bits
  clocksource/drivers/h8300_timer8: Fix wrong return value in h8300_8timer_init()
  ieee802154/adf7242: check status of adf7242_read_reg
  ieee802154: fix one possible memleak in ca8210_dev_com_init
  objtool: Fix noreturn detection for ignored functions
  i2c: core: Call i2c_acpi_install_space_handler() before i2c_acpi_register_devices()
  s390/init: add missing __init annotations
  btrfs: qgroup: fix data leak caused by race between writeback and truncate
  vfio/pci: fix racy on error and request eventfd ctx
  selftests/x86/syscall_nt: Clear weird flags after each test
  scsi: libfc: Skip additional kref updating work event
  scsi: libfc: Handling of extra kref
  cifs: Fix double add page to memcg when cifs_readpages
  vfio/pci: Clear error and request eventfd ctx after releasing
  x86/speculation/mds: Mark mds_user_clear_cpu_buffers() __always_inline
  mtd: parser: cmdline: Support MTD names containing one or more colons
  rapidio: avoid data race between file operation callbacks and mport_cdev_add().
  mm/swap_state: fix a data race in swapin_nr_pages
  ceph: fix potential race in ceph_check_caps
  mtd: rawnand: omap_elm: Fix runtime PM imbalance on error
  perf kcore_copy: Fix module map when there are no modules loaded
  perf util: Fix memory leak of prefix_if_not_in
  vfio/pci: fix memory leaks of eventfd ctx
  btrfs: don't force read-only after error in drop snapshot
  usb: dwc3: Increase timeout for CmdAct cleared by device controller
  printk: handle blank console arguments passed in.
  drm/nouveau/debugfs: fix runtime pm imbalance on error
  e1000: Do not perform reset in reset_task if we are already down
  arm64/cpufeature: Drop TraceFilt feature exposure from ID_DFR0 register
  USB: EHCI: ehci-mv: fix less than zero comparison of an unsigned int
  fuse: don't check refcount after stealing page
  powerpc/traps: Make unrecoverable NMIs die instead of panic
  ALSA: hda: Fix potential race in unsol event handler
  tty: serial: samsung: Correct clock selection logic
  USB: EHCI: ehci-mv: fix error handling in mv_ehci_probe()
  Bluetooth: Handle Inquiry Cancel error after Inquiry Complete
  phy: samsung: s5pv210-usb2: Add delay after reset
  power: supply: max17040: Correct voltage reading
  atm: fix a memory leak of vcc->user_back
  dt-bindings: sound: wm8994: Correct required supplies based on actual implementaion
  arm64: cpufeature: Relax checks for AArch32 support at EL[0-2]
  sparc64: vcc: Fix error return code in vcc_probe()
  staging:r8188eu: avoid skb_clone for amsdu to msdu conversion
  drivers: char: tlclk.c: Avoid data race between init and interrupt handler
  bdev: Reduce time holding bd_mutex in sync in blkdev_close()
  KVM: Remove CREATE_IRQCHIP/SET_PIT2 race
  serial: uartps: Wait for tx_empty in console setup
  scsi: qedi: Fix termination timeouts in session logout
  mm/mmap.c: initialize align_offset explicitly for vm_unmapped_area
  mm/vmscan.c: fix data races using kswapd_classzone_idx
  mm/filemap.c: clear page error before actual read
  mm/kmemleak.c: use address-of operator on section symbols
  NFS: Fix races nfs_page_group_destroy() vs nfs_destroy_unlinked_subrequests()
  ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra endpoint descriptor
  ubifs: Fix out-of-bounds memory access caused by abnormal value of node_len
  svcrdma: Fix leak of transport addresses
  SUNRPC: Fix a potential buffer overflow in 'svc_print_xprts()'
  RDMA/rxe: Set sys_image_guid to be aligned with HW IB devices
  tools: gpio-hammer: Avoid potential overflow in main
  cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_work_fn
  perf cpumap: Fix snprintf overflow check
  serial: 8250: 8250_omap: Terminate DMA before pushing data on RX timeout
  serial: 8250_omap: Fix sleeping function called from invalid context during probe
  serial: 8250_port: Don't service RX FIFO if throttled
  tracing: Use address-of operator on section symbols
  rtc: ds1374: fix possible race condition
  tpm: ibmvtpm: Wait for buffer to be set before proceeding
  xfs: don't ever return a stale pointer from __xfs_dir3_free_read
  media: tda10071: fix unsigned sign extension overflow
  Bluetooth: L2CAP: handle l2cap config request during open state
  scsi: aacraid: Disabling TM path and only processing IOP reset
  ath10k: use kzalloc to read for ath10k_sdio_hif_diag_read
  drm/amdgpu: increase atombios cmd timeout
  mm: avoid data corruption on CoW fault into PFN-mapped VMA
  ext4: fix a data race at inode->i_disksize
  timekeeping: Prevent 32bit truncation in scale64_check_overflow()
  Bluetooth: guard against controllers sending zero'd events
  media: go7007: Fix URB type for interrupt handling
  dmaengine: tegra-apb: Prevent race conditions on channel's freeing
  bpf: Remove recursion prevention from rcu free callback
  x86/pkeys: Add check for pkey "overflow"
  media: staging/imx: Missing assignment in imx_media_capture_device_register()
  KVM: x86: fix incorrect comparison in trace event
  RDMA/rxe: Fix configuration of atomic queue pair attributes
  perf test: Fix test trace+probe_vfs_getname.sh on s390
  drm/omap: fix possible object reference leak
  scsi: lpfc: Fix coverity errors in fmdi attribute handling
  scsi: lpfc: Fix RQ buffer leakage when no IOCBs available
  selinux: sel_avc_get_stat_idx should increase position index
  audit: CONFIG_CHANGE don't log internal bookkeeping as an event
  skbuff: fix a data race in skb_queue_len()
  ALSA: hda: Clear RIRB status before reading WP
  KVM: fix overflow of zero page refcount with ksm running
  Bluetooth: prefetch channel before killing sock
  mm: pagewalk: fix termination condition in walk_pte_range()
  Bluetooth: Fix refcount use-after-free issue
  tools/power/x86/intel_pstate_tracer: changes for python 3 compatibility
  selftests/ftrace: fix glob selftest
  ar5523: Add USB ID of SMCWUSBT-G2 wireless adapter
  tracing: Set kernel_stack's caller size properly
  powerpc/eeh: Only dump stack once if an MMIO loop is detected
  dmaengine: zynqmp_dma: fix burst length configuration
  ACPI: EC: Reference count query handlers under lock
  media: ti-vpe: cal: Restrict DMA to avoid memory corruption
  seqlock: Require WRITE_ONCE surrounding raw_seqcount_barrier
  rt_cpu_seq_next should increase position index
  neigh_stat_seq_next() should increase position index
  kernel/sys.c: avoid copying possible padding bytes in copy_to_user
  CIFS: Properly process SMB3 lease breaks
  debugfs: Fix !DEBUG_FS debugfs_create_automount
  gfs2: clean up iopen glock mess in gfs2_create_inode
  mmc: core: Fix size overflow for mmc partitions
  RDMA/iw_cgxb4: Fix an error handling path in 'c4iw_connect()'
  xfs: fix attr leaf header freemap.size underflow
  RDMA/i40iw: Fix potential use after free
  bcache: fix a lost wake-up problem caused by mca_cannibalize_lock
  tracing: Adding NULL checks for trace_array descriptor pointer
  mfd: mfd-core: Protect against NULL call-back function pointer
  mtd: cfi_cmdset_0002: don't free cfi->cfiq in error path of cfi_amdstd_setup()
  clk/ti/adpll: allocate room for terminating null
  scsi: fnic: fix use after free
  PM / devfreq: tegra30: Fix integer overflow on CPU's freq max out
  ALSA: hda/realtek - Couldn't detect Mic if booting with headset plugged
  ALSA: usb-audio: Add delay quirk for H570e USB headsets
  x86/ioapic: Unbreak check_timer()
  arch/x86/lib/usercopy_64.c: fix __copy_user_flushcache() cache writeback
  media: smiapp: Fix error handling at NVM reading
  ASoC: kirkwood: fix IRQ error handling
  gma/gma500: fix a memory disclosure bug due to uninitialized bytes
  m68k: q40: Fix info-leak in rtc_ioctl
  scsi: aacraid: fix illegal IO beyond last LBA
  mm: fix double page fault on arm64 if PTE_AF is cleared
  serial: 8250: Avoid error message on reprobe
  geneve: add transport ports in route lookup for geneve
  ipv4: Update exception handling for multipath routes via same device
  net: add __must_check to skb_put_padto()
  net: phy: Avoid NPD upon phy_detach() when driver is unbound
  bnxt_en: Protect bnxt_set_eee() and bnxt_set_pauseparam() with mutex.
  tipc: use skb_unshare() instead in tipc_buf_append()
  tipc: fix shutdown() of connection oriented socket
  net: ipv6: fix kconfig dependency warning for IPV6_SEG6_HMAC
  ip: fix tos reflection in ack and reset packets
  hdlc_ppp: add range checks in ppp_cp_parse_cr()
  RDMA/ucma: ucma_context reference leak in error path
  mm/thp: fix __split_huge_pmd_locked() for migration PMD
  kprobes: fix kill kprobe which has been marked as gone
  KVM: fix memory leak in kvm_io_bus_unregister_dev()
  phy: qcom-qmp: Use correct values for ipq8074 PCIe Gen2 PHY init
  af_key: pfkey_dump needs parameter validation
  ANDROID: Fix 64/32 compat issue with virtio_gpu_resource_create_blob
  ANDROID: Delete goldfish build configs and defconfigs
  Linux 4.14.199
  x86/defconfig: Enable CONFIG_USB_XHCI_HCD=y
  powerpc/dma: Fix dma_map_ops::get_required_mask
  ehci-hcd: Move include to keep CRC stable
  serial: 8250_pci: Add Realtek 816a and 816b
  Input: i8042 - add Entroware Proteus EL07R4 to nomux and reset lists
  Input: trackpoint - add new trackpoint variant IDs
  percpu: fix first chunk size calculation for populated bitmap
  i2c: i801: Fix resume bug
  usblp: fix race between disconnect() and read()
  USB: UAS: fix disconnect by unplugging a hub
  USB: quirks: Add USB_QUIRK_IGNORE_REMOTE_WAKEUP quirk for BYD zhaoxin notebook
  drm/mediatek: Add missing put_device() call in mtk_hdmi_dt_parse_pdata()
  drm/mediatek: Add exception handing in mtk_drm_probe() if component init fail
  MIPS: SNI: Fix spurious interrupts
  fbcon: Fix user font detection test at fbcon_resize().
  perf test: Free formats for perf pmu parse test
  MIPS: SNI: Fix MIPS_L1_CACHE_SHIFT
  Drivers: hv: vmbus: Add timeout to vmbus_wait_for_unload
  clk: rockchip: Fix initialization of mux_pll_src_4plls_p
  KVM: MIPS: Change the definition of kvm type
  spi: Fix memory leak on splited transfers
  i2c: algo: pca: Reapply i2c bus settings after reset
  f2fs: fix indefinite loop scanning for free nid
  nvme-fc: cancel async events before freeing event struct
  rapidio: Replace 'select' DMAENGINES 'with depends on'
  SUNRPC: stop printk reading past end of string
  spi: spi-loopback-test: Fix out-of-bounds read
  scsi: lpfc: Fix FLOGI/PLOGI receive race condition in pt2pt discovery
  scsi: libfc: Fix for double free()
  scsi: pm8001: Fix memleak in pm8001_exec_internal_task_abort
  NFSv4.1 handle ERR_DELAY error reclaiming locking state on delegation recall
  hv_netvsc: Remove "unlikely" from netvsc_select_queue
  net: handle the return value of pskb_carve_frag_list() correctly
  gfs2: initialize transaction tr_ailX_lists earlier
  gcov: add support for GCC 10.1
  usb: typec: ucsi: acpi: Check the _DEP dependencies
  usb: Fix out of sync data toggle if a configured device is reconfigured
  USB: serial: option: add support for SIM7070/SIM7080/SIM7090 modules
  USB: serial: option: support dynamic Quectel USB compositions
  USB: serial: ftdi_sio: add IDs for Xsens Mti USB converter
  usb: core: fix slab-out-of-bounds Read in read_descriptors
  staging: greybus: audio: fix uninitialized value issue
  video: fbdev: fix OOB read in vga_8planes_imageblit()
  ARM: dts: vfxxx: Add syscon compatible with OCOTP
  KVM: VMX: Don't freeze guest when event delivery causes an APIC-access exit
  vgacon: remove software scrollback support
  fbcon: remove now unusued 'softback_lines' cursor() argument
  fbcon: remove soft scrollback code
  RDMA/rxe: Fix the parent sysfs read when the interface has 15 chars
  rbd: require global CAP_SYS_ADMIN for mapping and unmapping
  scsi: target: iscsi: Fix hang in iscsit_access_np() when getting tpg->np_login_sem
  scsi: target: iscsi: Fix data digest calculation
  regulator: push allocation in set_consumer_device_supply() out of lock
  btrfs: fix wrong address when faulting in pages in the search ioctl
  btrfs: fix lockdep splat in add_missing_dev
  btrfs: require only sector size alignment for parent eb bytenr
  staging: wlan-ng: fix out of bounds read in prism2sta_probe_usb()
  iio:accel:mma8452: Fix timestamp alignment and prevent data leak.
  iio:accel:mma7455: Fix timestamp alignment and prevent data leak.
  iio: accel: kxsd9: Fix alignment of local buffer.
  iio:chemical:ccs811: Fix timestamp alignment and prevent data leak.
  iio:light:max44000 Fix timestamp alignment and prevent data leak.
  iio:magnetometer:ak8975 Fix alignment and data leak issues.
  iio:adc:ti-adc081c Fix alignment and data leak issues
  iio:adc:max1118 Fix alignment of timestamp and data leak issues
  iio:adc:ina2xx Fix timestamp alignment issue.
  iio:adc:ti-adc084s021 Fix alignment and data leak issues.
  iio:accel:bmc150-accel: Fix timestamp alignment and prevent data leak.
  iio:light:ltr501 Fix timestamp alignment issue.
  iio: adc: ti-ads1015: fix conversion when CONFIG_PM is not set
  iio: adc: mcp3422: fix locking on error path
  iio: adc: mcp3422: fix locking scope
  gcov: Disable gcov build with GCC 10
  ALSA: hda: fix a runtime pm issue in SOF when integrated GPU is disabled
  cpufreq: intel_pstate: Refuse to turn off with HWP enabled
  ARC: [plat-hsdk]: Switch ethernet phy-mode to rgmii-id
  drivers/net/wan/hdlc_cisco: Add hard_header_len
  irqchip/eznps: Fix build error for !ARC700 builds
  xfs: initialize the shortform attr header padding entry
  drivers/net/wan/lapbether: Set network_header before transmitting
  ALSA: hda: Fix 2 channel swapping for Tegra
  firestream: Fix memleak in fs_open
  NFC: st95hf: Fix memleak in st95hf_in_send_cmd
  drivers/net/wan/lapbether: Added needed_tailroom
  dmaengine: acpi: Put the CSRT table after using it
  ARC: HSDK: wireup perf irq
  arm64: dts: ns2: Fixed QSPI compatible string
  ARM: dts: BCM5301X: Fixed QSPI compatible string
  mmc: sdhci-msm: Add retries when all tuning phases are found valid
  RDMA/core: Fix reported speed and width
  scsi: libsas: Set data_dir as DMA_NONE if libata marks qc as NODATA
  RDMA/rxe: Drop pointless checks in rxe_init_ports
  RDMA/rxe: Fix memleak in rxe_mem_init_user
  ARM: dts: socfpga: fix register entry for timer3 on Arria10
  ANDROID: Add INIT_STACK_ALL_ZERO to the list of Clang-specific options
  Linux 4.14.198
  net: disable netpoll on fresh napis
  tipc: fix shutdown() of connectionless socket
  sctp: not disable bh in the whole sctp_get_port_local()
  net: usb: dm9601: Add USB ID of Keenetic Plus DSL
  netlabel: fix problems with mapping removal
  bnxt: don't enable NAPI until rings are ready
  vfio/pci: Fix SR-IOV VF handling with MMIO blocking
  vfio-pci: Invalidate mmaps and block MMIO access on disabled memory
  vfio-pci: Fault mmaps to enable vma tracking
  vfio/type1: Support faulting PFNMAP vmas
  block: ensure bdi->io_pages is always initialized
  ALSA; firewire-tascam: exclude Tascam FE-8 from detection
  Linux 4.14.197
  net: usb: Fix uninit-was-stored issue in asix_read_phy_addr()
  cfg80211: regulatory: reject invalid hints
  mm/hugetlb: fix a race between hugetlb sysctl handlers
  checkpatch: fix the usage of capture group ( ... )
  KVM: arm64: Set HCR_EL2.PTW to prevent AT taking synchronous exception
  KVM: arm64: Survive synchronous exceptions caused by AT instructions
  KVM: arm64: Defer guest entry when an asynchronous exception is pending
  KVM: arm64: Add kvm_extable for vaxorcism code
  mm: slub: fix conversion of freelist_corrupted()
  dm thin metadata: Avoid returning cmd->bm wild pointer on error
  dm cache metadata: Avoid returning cmd->bm wild pointer on error
  libata: implement ATA_HORKAGE_MAX_TRIM_128M and apply to Sandisks
  block: Move SECTOR_SIZE and SECTOR_SHIFT definitions into <linux/blkdev.h>
  block: allow for_each_bvec to support zero len bvec
  affs: fix basic permission bits to actually work
  ALSA: firewire-digi00x: exclude Avid Adrenaline from detection
  ALSA: hda/hdmi: always check pin power status in i915 pin fixup
  ALSA: pcm: oss: Remove superfluous WARN_ON() for mulaw sanity check
  ALSA: ca0106: fix error code handling
  usb: qmi_wwan: add D-Link DWM-222 A2 device ID
  net: usb: qmi_wwan: add Telit 0x1050 composition
  btrfs: fix potential deadlock in the search ioctl
  uaccess: Add non-pagefault user-space write function
  uaccess: Add non-pagefault user-space read functions
  btrfs: set the lockdep class for log tree extent buffers
  btrfs: Remove extraneous extent_buffer_get from tree_mod_log_rewind
  btrfs: Remove redundant extent_buffer_get in get_old_root
  btrfs: drop path before adding new uuid tree entry
  include/linux/log2.h: add missing () around n in roundup_pow_of_two()
  thermal: ti-soc-thermal: Fix bogus thermal shutdowns for omap4430
  iommu/vt-d: Serialize IOMMU GCMD register modifications
  tg3: Fix soft lockup when tg3_reset_task() fails.
  fix regression in "epoll: Keep a reference on files added to the check list"
  net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init()
  perf tools: Correct SNOOPX field offset
  nvmet-fc: Fix a missed _irqsave version of spin_lock in 'nvmet_fc_fod_op_done()'
  bnxt_en: Fix PCI AER error recovery flow
  bnxt_en: Check for zero dir entries in NVRAM.
  gtp: add GTPA_LINK info to msg sent to userspace
  dmaengine: pl330: Fix burst length if burst size is smaller than bus width
  net: arc_emac: Fix memleak in arc_mdio_probe
  ravb: Fixed to be able to unload modules
  net: systemport: Fix memleak in bcm_sysport_probe
  net: hns: Fix memleak in hns_nic_dev_probe
  netfilter: nf_tables: fix destination register zeroing
  netfilter: nf_tables: incorrect enum nft_list_attributes definition
  netfilter: nf_tables: add NFTA_SET_USERDATA if not null
  MIPS: BMIPS: Also call bmips_cpu_setup() for secondary cores
  MIPS: mm: BMIPS5000 has inclusive physical caches
  dmaengine: at_hdmac: check return value of of_find_device_by_node() in at_dma_xlate()
  batman-adv: bla: use netif_rx_ni when not in interrupt context
  batman-adv: Fix own OGM check in aggregated OGMs
  batman-adv: Avoid uninitialized chaddr when handling DHCP
  dmaengine: of-dma: Fix of_dma_router_xlate's of_dma_xlate handling
  xen/xenbus: Fix granting of vmalloc'd memory
  s390: don't trace preemption in percpu macros
  cpuidle: Fixup IRQ state
  ceph: don't allow setlease on cephfs
  nvmet: Disable keep-alive timer when kato is cleared to 0h
  hwmon: (applesmc) check status earlier.
  drm/msm: add shutdown support for display platform_driver
  perf record/stat: Explicitly call out event modifiers in the documentation
  HID: core: Sanitize event code and type when mapping input
  HID: core: Correctly handle ReportSize being zero
  Linux 4.14.196
  ALSA: usb-audio: Update documentation comment for MS2109 quirk
  HID: hiddev: Fix slab-out-of-bounds write in hiddev_ioctl_usage()
  tpm: Unify the mismatching TPM space buffer sizes
  btrfs: check the right error variable in btrfs_del_dir_entries_in_log
  usb: storage: Add unusual_uas entry for Sony PSZ drives
  USB: cdc-acm: rework notification_buffer resizing
  USB: gadget: u_f: Unbreak offset calculation in VLAs
  USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()
  USB: gadget: u_f: add overflow checks to VLA macros
  overflow.h: Add allocation size calculation helpers
  usb: host: ohci-exynos: Fix error handling in exynos_ohci_probe()
  USB: Ignore UAS for JMicron JMS567 ATA/ATAPI Bridge
  USB: quirks: Add no-lpm quirk for another Raydium touchscreen
  usb: uas: Add quirk for PNY Pro Elite
  USB: yurex: Fix bad gfp argument
  drm/amdgpu: Fix buffer overflow in INFO ioctl
  device property: Fix the secondary firmware node handling in set_primary_fwnode()
  PM: sleep: core: Fix the handling of pending runtime resume requests
  xhci: Do warm-reset when both CAS and XDEV_RESUME are set
  XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN data pointer which contains XEN specific information.
  writeback: Fix sync livelock due to b_dirty_time processing
  writeback: Avoid skipping inode writeback
  writeback: Protect inode->i_io_list with inode->i_lock
  serial: 8250: change lock order in serial8250_do_startup()
  serial: 8250_exar: Fix number of ports for Commtech PCIe cards
  serial: pl011: Don't leak amba_ports entry on driver register error
  serial: pl011: Fix oops on -EPROBE_DEFER
  serial: samsung: Removes the IRQ not found warning
  vt_ioctl: change VT_RESIZEX ioctl to check for error return from vc_resize()
  vt: defer kfree() of vc_screenbuf in vc_do_resize()
  USB: lvtest: return proper error code in probe
  fbcon: prevent user font height or width change from causing potential out-of-bounds access
  btrfs: fix space cache memory leak after transaction abort
  HID: i2c-hid: Always sleep 60ms after I2C_HID_PWR_ON commands
  powerpc/perf: Fix soft lockups due to missed interrupt accounting
  net: gianfar: Add of_node_put() before goto statement
  scsi: ufs: Clean up completed request without interrupt notification
  scsi: ufs: Improve interrupt handling for shared interrupts
  scsi: ufs: Fix possible infinite loop in ufshcd_hold
  s390/cio: add cond_resched() in the slow_eval_known_fn() loop
  spi: stm32: fix stm32_spi_prepare_mbr in case of odd clk_rate
  fs: prevent BUG_ON in submit_bh_wbc()
  jbd2: abort journal if free a async write error metadata buffer
  ext4: don't BUG on inconsistent journal feature
  jbd2: make sure jh have b_transaction set in refile/unfile_buffer
  usb: gadget: f_tcm: Fix some resource leaks in some error paths
  i2c: rcar: in slave mode, clear NACK earlier
  null_blk: fix passing of REQ_FUA flag in null_handle_rq
  nvme-fc: Fix wrong return value in __nvme_fc_init_request()
  media: gpio-ir-tx: improve precision of transmitted signal due to scheduling
  Revert "ath10k: fix DMA related firmware crashes on multiple devices"
  efi: provide empty efi_enter_virtual_mode implementation
  USB: sisusbvga: Fix a potential UB casued by left shifting a negative value
  powerpc/spufs: add CONFIG_COREDUMP dependency
  KVM: arm64: Fix symbol dependency in __hyp_call_panic_nvhe
  media: davinci: vpif_capture: fix potential double free
  EDAC/ie31200: Fallback if host bridge device is already initialized
  scsi: fcoe: Memory leak fix in fcoe_sysfs_fcf_del()
  ceph: fix potential mdsc use-after-free crash
  scsi: iscsi: Do not put host in iscsi_set_flashnode_param()
  locking/lockdep: Fix overflow in presentation of average lock-time
  drm/nouveau: Fix reference count leak in nouveau_connector_detect
  drm/nouveau/drm/noveau: fix reference count leak in nouveau_fbcon_open
  f2fs: fix use-after-free issue
  cec-api: prevent leaking memory through hole in structure
  mips/vdso: Fix resource leaks in genvdso.c
  rtlwifi: rtl8192cu: Prevent leaking urb
  PCI: Fix pci_create_slot() reference count leak
  omapfb: fix multiple reference count leaks due to pm_runtime_get_sync
  selftests/powerpc: Purge extra count_pmc() calls of ebb selftests
  scsi: lpfc: Fix shost refcount mismatch when deleting vport
  drm/amdgpu/display: fix ref count leak when pm_runtime_get_sync fails
  drm/amdgpu: fix ref count leak in amdgpu_display_crtc_set_config
  drm/amd/display: fix ref count leak in amdgpu_drm_ioctl
  drm/amdgpu: fix ref count leak in amdgpu_driver_open_kms
  drm/radeon: fix multiple reference count leak
  drm/amdkfd: Fix reference count leaks.
  iommu/iova: Don't BUG on invalid PFNs
  scsi: target: tcmu: Fix crash on ARM during cmd completion
  blktrace: ensure our debugfs dir exists
  media: pci: ttpci: av7110: fix possible buffer overflow caused by bad DMA value in debiirq()
  powerpc/xive: Ignore kmemleak false positives
  arm64: dts: qcom: msm8916: Pull down PDM GPIOs during sleep
  mfd: intel-lpss: Add Intel Emmitsburg PCH PCI IDs
  ASoC: tegra: Fix reference count leaks.
  ALSA: pci: delete repeated words in comments
  gre6: Fix reception with IP6_TNL_F_RCV_DSCP_COPY
  ipvlan: fix device features
  tipc: fix uninit skb->data in tipc_nl_compat_dumpit()
  net: Fix potential wrong skb->protocol in skb_vlan_untag()
  powerpc/64s: Don't init FSCR_DSCR in __init_FSCR()
  ANDROID: cuttlefish_defconfig: initialize locals with zeroes
  BACKPORT: security: allow using Clang's zero initialization for stack variables
  Revert "binder: Prevent context manager from incrementing ref 0"
  Linux 4.14.195
  KVM: arm/arm64: Don't reschedule in unmap_stage2_range()
  clk: Evict unregistered clks from parent caches
  xen: don't reschedule in preemption off sections
  mm/hugetlb: fix calculation of adjust_range_if_pmd_sharing_possible
  do_epoll_ctl(): clean the failure exits up a bit
  epoll: Keep a reference on files added to the check list
  powerpc/pseries: Do not initiate shutdown when system is running on UPS
  net: dsa: b53: check for timeout
  hv_netvsc: Fix the queue_mapping in netvsc_vf_xmit()
  bonding: fix active-backup failover for current ARP slave
  vfio/type1: Add proper error unwind for vfio_iommu_replay()
  ASoC: intel: Fix memleak in sst_media_open
  ASoC: msm8916-wcd-analog: fix register Interrupt offset
  bonding: fix a potential double-unregister
  bonding: show saner speed for broadcast mode
  net: fec: correct the error path for regulator disable in probe
  i40e: Fix crash during removing i40e driver
  i40e: Set RX_ONLY mode for unicast promiscuous on VLAN
  ext4: fix potential negative array index in do_split()
  alpha: fix annotation of io{read,write}{16,32}be()
  xfs: Fix UBSAN null-ptr-deref in xfs_sysfs_init
  virtio_ring: Avoid loop when vq is broken in virtqueue_poll
  scsi: libfc: Free skb in fc_disc_gpn_id_resp() for valid cases
  cpufreq: intel_pstate: Fix cpuinfo_max_freq when MSR_TURBO_RATIO_LIMIT is 0
  jffs2: fix UAF problem
  xfs: fix inode quota reservation checks
  m68knommu: fix overwriting of bits in ColdFire V3 cache control
  Input: psmouse - add a newline when printing 'proto' by sysfs
  media: vpss: clean up resources in init
  rtc: goldfish: Enable interrupt in set_alarm() when necessary
  media: budget-core: Improve exception handling in budget_register()
  scsi: ufs: Add DELAY_BEFORE_LPM quirk for Micron devices
  spi: Prevent adding devices below an unregistering controller
  jbd2: add the missing unlock_buffer() in the error path of jbd2_write_superblock()
  ext4: fix checking of directory entry validity for inline directories
  mm, page_alloc: fix core hung in free_pcppages_bulk()
  mm: include CMA pages in lowmem_reserve at boot
  kernel/relay.c: fix memleak on destroy relay channel
  romfs: fix uninitialized memory leak in romfs_dev_read()
  btrfs: sysfs: use NOFS for device creation
  btrfs: inode: fix NULL pointer dereference if inode doesn't need compression
  btrfs: Move free_pages_out label in inline extent handling branch in compress_file_range
  btrfs: don't show full path of bind mounts in subvol=
  btrfs: export helpers for subvolume name/id resolution
  powerpc: Allow 4224 bytes of stack expansion for the signal frame
  powerpc/mm: Only read faulting instruction when necessary in do_page_fault()
  khugepaged: adjust VM_BUG_ON_MM() in __khugepaged_enter()
  khugepaged: khugepaged_test_exit() check mmget_still_valid()
  perf probe: Fix memory leakage when the probe point is not found
  drm/vgem: Replace opencoded version of drm_gem_dumb_map_offset()
  ANDROID: virtio_gpu.h: move map/unmap to 3d group
  Linux 4.14.194
  dm cache: remove all obsolete writethrough-specific code
  dm cache: submit writethrough writes in parallel to origin and cache
  dm cache: pass cache structure to mode functions
  genirq/affinity: Make affinity setting if activated opt-in
  genirq/affinity: Handle affinity setting on inactive interrupts correctly
  khugepaged: retract_page_tables() remember to test exit
  sh: landisk: Add missing initialization of sh_io_port_base
  tools build feature: Quote CC and CXX for their arguments
  perf bench mem: Always memset source before memcpy
  ALSA: echoaudio: Fix potential Oops in snd_echo_resume()
  mfd: dln2: Run event handler loop under spinlock
  test_kmod: avoid potential double free in trigger_config_run_type()
  fs/ufs: avoid potential u32 multiplication overflow
  nfs: Fix getxattr kernel panic and memory overflow
  net: qcom/emac: add missed clk_disable_unprepare in error path of emac_clks_phase1_init
  drm/vmwgfx: Fix two list_for_each loop exit tests
  drm/vmwgfx: Use correct vmw_legacy_display_unit pointer
  Input: sentelic - fix error return when fsp_reg_write fails
  i2c: rcar: avoid race when unregistering slave
  tools build feature: Use CC and CXX from parent
  pwm: bcm-iproc: handle clk_get_rate() return
  clk: clk-atlas6: fix return value check in atlas6_clk_init()
  i2c: rcar: slave: only send STOP event when we have been addressed
  iommu/vt-d: Enforce PASID devTLB field mask
  iommu/omap: Check for failure of a call to omap_iommu_dump_ctx
  dm rq: don't call blk_mq_queue_stopped() in dm_stop_queue()
  gpu: ipu-v3: image-convert: Combine rotate/no-rotate irq handlers
  USB: serial: ftdi_sio: clean up receive processing
  USB: serial: ftdi_sio: make process-packet buffer unsigned
  RDMA/ipoib: Return void from ipoib_ib_dev_stop()
  mfd: arizona: Ensure 32k clock is put on driver unbind and error
  drm/imx: imx-ldb: Disable both channels for split mode in enc->disable()
  perf intel-pt: Fix FUP packet state
  pseries: Fix 64 bit logical memory block panic
  watchdog: f71808e_wdt: clear watchdog timeout occurred flag
  watchdog: f71808e_wdt: remove use of wrong watchdog_info option
  watchdog: f71808e_wdt: indicate WDIOF_CARDRESET support in watchdog_info.options
  tracing: Use trace_sched_process_free() instead of exit() for pid tracing
  tracing/hwlat: Honor the tracing_cpumask
  kprobes: Fix NULL pointer dereference at kprobe_ftrace_handler
  ftrace: Setup correct FTRACE_FL_REGS flags for module
  ocfs2: change slot number type s16 to u16
  ext2: fix missing percpu_counter_inc
  MIPS: CPU#0 is not hotpluggable
  mac80211: fix misplaced while instead of if
  bcache: allocate meta data pages as compound pages
  md/raid5: Fix Force reconstruct-write io stuck in degraded raid5
  net/compat: Add missing sock updates for SCM_RIGHTS
  net: stmmac: dwmac1000: provide multicast filter fallback
  net: ethernet: stmmac: Disable hardware multicast filter
  powerpc: Fix circular dependency between percpu.h and mmu.h
  xtensa: fix xtensa_pmu_setup prototype
  iio: dac: ad5592r: fix unbalanced mutex unlocks in ad5592r_read_raw()
  dt-bindings: iio: io-channel-mux: Fix compatible string in example code
  btrfs: fix memory leaks after failure to lookup checksums during inode logging
  btrfs: only search for left_info if there is no right_info in try_merge_free_space
  btrfs: don't allocate anonymous block device for user invisible roots
  PCI: hotplug: ACPI: Fix context refcounting in acpiphp_grab_context()
  smb3: warn on confusing error scenario with sec=krb5
  net: initialize fastreuse on inet_inherit_port
  xen/balloon: make the balloon wait interruptible
  xen/balloon: fix accounting in alloc_xenballooned_pages error path
  irqdomain/treewide: Free firmware node after domain removal
  ARM: 8992/1: Fix unwind_frame for clang-built kernels
  parisc: mask out enable and reserved bits from sba imask
  parisc: Implement __smp_store_release and __smp_load_acquire barriers
  mtd: rawnand: qcom: avoid write to unavailable register
  spi: spidev: Align buffers for DMA
  9p: Fix memory leak in v9fs_mount
  ALSA: usb-audio: work around streaming quirk for MacroSilicon MS2109
  fs/minix: reject too-large maximum file size
  fs/minix: don't allow getting deleted inodes
  fs/minix: check return value of sb_getblk()
  bitfield.h: don't compile-time validate _val in FIELD_FIT
  crypto: cpt - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not specified
  crypto: ccp - Fix use of merged scatterlists
  crypto: qat - fix double free in qat_uclo_create_batch_init_list
  ALSA: usb-audio: add quirk for Pioneer DDJ-RB
  ALSA: usb-audio: fix overeager device match for MacroSilicon MS2109
  ALSA: usb-audio: Creative USB X-Fi Pro SB1095 volume knob support
  USB: serial: cp210x: enable usb generic throttle/unthrottle
  USB: serial: cp210x: re-enable auto-RTS on open
  net: Set fput_needed iff FDPUT_FPUT is set
  net: refactor bind_bucket fastreuse into helper
  net/nfc/rawsock.c: add CAP_NET_RAW check.
  drivers/net/wan/lapbether: Added needed_headroom and a skb->len check
  af_packet: TPACKET_V3: fix fill status rwlock imbalance
  crypto: aesni - add compatibility with IAS
  x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task
  pinctrl-single: fix pcs_parse_pinconf() return value
  dlm: Fix kobject memleak
  fsl/fman: fix eth hash table allocation
  fsl/fman: check dereferencing null pointer
  fsl/fman: fix unreachable code
  fsl/fman: fix dereference null return value
  fsl/fman: use 32-bit unsigned integer
  net: spider_net: Fix the size used in a 'dma_free_coherent()' call
  liquidio: Fix wrong return value in cn23xx_get_pf_num()
  net: ethernet: aquantia: Fix wrong return value
  tools, build: Propagate build failures from tools/build/Makefile.build
  wl1251: fix always return 0 error
  s390/qeth: don't process empty bridge port events
  selftests/powerpc: Fix online CPU selection
  PCI: Release IVRS table in AMD ACS quirk
  selftests/powerpc: Fix CPU affinity for child process
  Bluetooth: hci_serdev: Only unregister device if it was registered
  power: supply: check if calc_soc succeeded in pm860x_init_battery
  Smack: prevent underflow in smk_set_cipso()
  Smack: fix another vsscanf out of bounds
  net: dsa: mv88e6xxx: MV88E6097 does not support jumbo configuration
  scsi: mesh: Fix panic after host or bus reset
  usb: dwc2: Fix error path in gadget registration
  MIPS: OCTEON: add missing put_device() call in dwc3_octeon_device_init()
  coresight: tmc: Fix TMC mode read in tmc_read_unprepare_etb()
  thermal: ti-soc-thermal: Fix reversed condition in ti_thermal_expose_sensor()
  USB: serial: iuu_phoenix: fix led-activity helpers
  drm/imx: tve: fix regulator_disable error path
  PCI/ASPM: Add missing newline in sysfs 'policy'
  staging: rtl8192u: fix a dubious looking mask before a shift
  powerpc/vdso: Fix vdso cpu truncation
  mwifiex: Prevent memory corruption handling keys
  scsi: scsi_debug: Add check for sdebug_max_queue during module init
  drm/bridge: sil_sii8620: initialize return of sii8620_readb
  drm: panel: simple: Fix bpc for LG LB070WV8 panel
  leds: core: Flush scheduled work for system suspend
  PCI: Fix pci_cfg_wait queue locking problem
  xfs: fix reflink quota reservation accounting error
  media: exynos4-is: Add missed check for pinctrl_lookup_state()
  media: firewire: Using uninitialized values in node_probe()
  ipvs: allow connection reuse for unconfirmed conntrack
  scsi: eesox: Fix different dev_id between request_irq() and free_irq()
  scsi: powertec: Fix different dev_id between request_irq() and free_irq()
  drm/radeon: fix array out-of-bounds read and write issues
  cxl: Fix kobject memleak
  drm/mipi: use dcs write for mipi_dsi_dcs_set_tear_scanline
  scsi: cumana_2: Fix different dev_id between request_irq() and free_irq()
  ASoC: Intel: bxt_rt298: add missing .owner field
  media: omap3isp: Add missed v4l2_ctrl_handler_free() for preview_init_entities()
  leds: lm355x: avoid enum conversion warning
  drm/arm: fix unintentional integer overflow on left shift
  iio: improve IIO_CONCENTRATION channel type description
  video: pxafb: Fix the function used to balance a 'dma_alloc_coherent()' call
  console: newport_con: fix an issue about leak related system resources
  video: fbdev: sm712fb: fix an issue about iounmap for a wrong address
  agp/intel: Fix a memory leak on module initialisation failure
  ACPICA: Do not increment operation_region reference counts for field units
  bcache: fix super block seq numbers comparision in register_cache_set()
  dyndbg: fix a BUG_ON in ddebug_describe_flags
  usb: bdc: Halt controller on suspend
  bdc: Fix bug causing crash after multiple disconnects
  usb: gadget: net2280: fix memory leak on probe error handling paths
  gpu: host1x: debug: Fix multiple channels emitting messages simultaneously
  iwlegacy: Check the return value of pcie_capability_read_*()
  brcmfmac: set state of hanger slot to FREE when flushing PSQ
  brcmfmac: To fix Bss Info flag definition Bug
  mm/mmap.c: Add cond_resched() for exit_mmap() CPU stalls
  irqchip/irq-mtk-sysirq: Replace spinlock with raw_spinlock
  drm/debugfs: fix plain echo to connector "force" attribute
  drm/nouveau: fix multiple instances of reference count leaks
  arm64: dts: hisilicon: hikey: fixes to comply with adi, adv7533 DT binding
  md-cluster: fix wild pointer of unlock_all_bitmaps()
  video: fbdev: neofb: fix memory leak in neo_scan_monitor()
  drm/radeon: Fix reference count leaks caused by pm_runtime_get_sync
  fs/btrfs: Add cond_resched() for try_release_extent_mapping() stalls
  Bluetooth: add a mutex lock to avoid UAF in do_enale_set
  drm/tilcdc: fix leak & null ref in panel_connector_get_modes
  ARM: socfpga: PM: add missing put_device() call in socfpga_setup_ocram_self_refresh()
  spi: lantiq: fix: Rx overflow error in full duplex mode
  ARM: at91: pm: add missing put_device() call in at91_pm_sram_init()
  platform/x86: intel-vbtn: Fix return value check in check_acpi_dev()
  platform/x86: intel-hid: Fix return value check in check_acpi_dev()
  m68k: mac: Fix IOP status/control register writes
  m68k: mac: Don't send IOP message until channel is idle
  arm64: dts: exynos: Fix silent hang after boot on Espresso
  arm64: dts: qcom: msm8916: Replace invalid bias-pull-none property
  EDAC: Fix reference count leaks
  arm64: dts: rockchip: fix rk3399-puma gmac reset gpio
  arm64: dts: rockchip: fix rk3399-puma vcc5v0-host gpio
  sched: correct SD_flags returned by tl->sd_flags()
  x86/mce/inject: Fix a wrong assignment of i_mce.status
  cgroup: add missing skcd->no_refcnt check in cgroup_sk_clone()
  HID: input: Fix devices that return multiple bytes in battery report
  tracepoint: Mark __tracepoint_string's __used
  Smack: fix use-after-free in smk_write_relabel_self()
  rxrpc: Fix race between recvmsg and sendmsg on immediate call failure
  usb: hso: check for return value in hso_serial_common_create()
  selftests/net: relax cpu affinity requirement in msg_zerocopy test
  Revert "vxlan: fix tos value before xmit"
  openvswitch: Prevent kernel-infoleak in ovs_ct_put_key()
  net: gre: recompute gre csum for sctp over gre tunnels
  hv_netvsc: do not use VF device if link is down
  net: lan78xx: replace bogus endpoint lookup
  vxlan: Ensure FDB dump is performed under RCU
  net: ethernet: mtk_eth_soc: fix MTU warnings
  ipv6: fix memory leaks on IPV6_ADDRFORM path
  ipv4: Silence suspicious RCU usage warning
  xattr: break delegations in {set,remove}xattr
  Drivers: hv: vmbus: Ignore CHANNELMSG_TL_CONNECT_RESULT(23)
  tools lib traceevent: Fix memory leak in process_dynamic_array_len
  atm: fix atm_dev refcnt leaks in atmtcp_remove_persistent
  igb: reinit_locked() should be called with rtnl_lock
  cfg80211: check vendor command doit pointer before use
  i2c: slave: add sanity check when unregistering
  i2c: slave: improve sanity check when registering
  drm/nouveau/fbcon: zero-initialise the mode_cmd2 structure
  drm/nouveau/fbcon: fix module unload when fbcon init has failed for some reason
  net/9p: validate fds in p9_fd_open
  leds: 88pm860x: fix use-after-free on unbind
  leds: lm3533: fix use-after-free on unbind
  leds: da903x: fix use-after-free on unbind
  leds: wm831x-status: fix use-after-free on unbind
  mtd: properly check all write ioctls for permissions
  vgacon: Fix for missing check in scrollback handling
  binder: Prevent context manager from incrementing ref 0
  omapfb: dss: Fix max fclk divider for omap36xx
  Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_with_rssi_evt()
  Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_evt()
  Bluetooth: Fix slab-out-of-bounds read in hci_extended_inquiry_result_evt()
  staging: android: ashmem: Fix lockdep warning for write operation
  ALSA: seq: oss: Serialize ioctls
  usb: xhci: Fix ASMedia ASM1142 DMA addressing
  usb: xhci: define IDs for various ASMedia host controllers
  USB: iowarrior: fix up report size handling for some devices
  net/mlx5e: Don't support phys switch id if not in switchdev mode
  USB: serial: qcserial: add EM7305 QDL product ID
  ANDROID: tty: fix tty name overflow
  ANDROID: fix a bug in quota2
  ANDROID: Incremental fs: fix magic compatibility again
  Linux 4.14.193
  ARM: 8702/1: head-common.S: Clear lr before jumping to start_kernel()
  ext4: fix direct I/O read error
  random32: move the pseudo-random 32-bit definitions to prandom.h
  random32: remove net_rand_state from the latent entropy gcc plugin
  random: fix circular include dependency on arm64 after addition of percpu.h
  ARM: percpu.h: fix build error
  random32: update the net random state on interrupt and activity
  Revert "scsi: libsas: direct call probe and destruct"
  Linux 4.14.192
  x86/i8259: Use printk_deferred() to prevent deadlock
  KVM: LAPIC: Prevent setting the tscdeadline timer if the lapic is hw disabled
  xen-netfront: fix potential deadlock in xennet_remove()
  cxgb4: add missing release on skb in uld_send()
  x86/unwind/orc: Fix ORC for newly forked tasks
  Revert "i2c: cadence: Fix the hold bit setting"
  net: ethernet: ravb: exit if re-initialization fails in tx timeout
  parisc: add support for cmpxchg on u8 pointers
  nfc: s3fwrn5: add missing release on skb in s3fwrn5_recv_frame
  qed: Disable "MFW indication via attention" SPAM every 5 minutes
  usb: hso: Fix debug compile warning on sparc32
  arm64: csum: Fix handling of bad packets
  arm64/alternatives: move length validation inside the subsection
  mac80211: mesh: Free pending skb when destroying a mpath
  mac80211: mesh: Free ie data when leaving mesh
  bpf: Fix map leak in HASH_OF_MAPS map
  ibmvnic: Fix IRQ mapping disposal in error path
  mlxsw: core: Free EMAD transactions using kfree_rcu()
  mlxsw: core: Increase scope of RCU read-side critical section
  mlx4: disable device on shutdown
  net: lan78xx: fix transfer-buffer memory leak
  net: lan78xx: add missing endpoint sanity check
  sh: Fix validation of system call number
  selftests/net: rxtimestamp: fix clang issues for target arch PowerPC
  net/x25: Fix null-ptr-deref in x25_disconnect
  net/x25: Fix x25_neigh refcnt leak when x25 disconnect
  xfs: fix missed wakeup on l_flush_wait
  rds: Prevent kernel-infoleak in rds_notify_queue_get()
  x86, vmlinux.lds: Page-align end of ..page_aligned sections
  x86/build/lto: Fix truncated .bss with -fdata-sections
  9p/trans_fd: Fix concurrency del of req_list in p9_fd_cancelled/p9_read_work
  9p/trans_fd: abort p9_read_work if req status changed
  f2fs: check if file namelen exceeds max value
  f2fs: check memory boundary by insane namelen
  drm: hold gem reference until object is no longer accessed
  drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl()
  ARM: 8986/1: hw_breakpoint: Don't invoke overflow handler on uaccess watchpoints
  wireless: Use offsetof instead of custom macro.
  PCI/ASPM: Disable ASPM on ASMedia ASM1083/1085 PCIe-to-PCI bridge
  x86/kvm: Be careful not to clear KVM_VCPU_FLUSH_TLB bit
  ath9k: release allocated buffer if timed out
  ath9k_htc: release allocated buffer if timed out
  iio: imu: adis16400: fix memory leak
  media: rc: prevent memory leak in cx23888_ir_probe
  crypto: ccp - Release all allocated memory if sha type is invalid
  net: phy: mdio-bcm-unimac: fix potential NULL dereference in unimac_mdio_probe()
  scsi: libsas: direct call probe and destruct
  Linux 4.14.191
  xfs: set format back to extents if xfs_bmap_extents_to_btree
  regmap: debugfs: check count when read regmap file
  mm/page_owner.c: remove drain_all_pages from init_early_allocated_pages
  tcp: allow at most one TLP probe per flight
  rtnetlink: Fix memory(net_device) leak when ->newlink fails
  ip6_gre: fix null-ptr-deref in ip6gre_init_net()
  AX.25: Prevent integer overflows in connect and sendmsg
  rxrpc: Fix sendmsg() returning EPIPE due to recvmsg() returning ENODATA
  net: udp: Fix wrong clean up for IS_UDPLITE macro
  net-sysfs: add a newline when printing 'tx_timeout' by sysfs
  drivers/net/wan/x25_asy: Fix to make it work
  dev: Defer free of skbs in flush_backlog
  AX.25: Prevent out-of-bounds read in ax25_sendmsg()
  AX.25: Fix out-of-bounds read in ax25_connect()
  Linux 4.14.190
  ath9k: Fix regression with Atheros 9271
  ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb
  parisc: Add atomic64_set_release() define to avoid CPU soft lockups
  io-mapping: indicate mapping failure
  mm/memcg: fix refcount error while moving and swapping
  Makefile: Fix GCC_TOOLCHAIN_DIR prefix for Clang cross compilation
  vt: Reject zero-sized screen buffer size.
  fbdev: Detect integer underflow at "struct fbcon_ops"->clear_margins.
  serial: 8250_mtk: Fix high-speed baud rates clamping
  serial: 8250: fix null-ptr-deref in serial8250_start_tx()
  staging: comedi: addi_apci_1564: check INSN_CONFIG_DIGITAL_TRIG shift
  staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
  staging: comedi: ni_6527: fix INSN_CONFIG_DIGITAL_TRIG support
  staging: comedi: addi_apci_1032: check INSN_CONFIG_DIGITAL_TRIG shift
  staging: wlan-ng: properly check endpoint types
  Revert "cifs: Fix the target file was deleted when rename failed."
  usb: xhci: Fix ASM2142/ASM3142 DMA addressing
  usb: xhci-mtk: fix the failure of bandwidth allocation
  binder: Don't use mmput() from shrinker function.
  x86: math-emu: Fix up 'cmp' insn for clang ias
  arm64: Use test_tsk_thread_flag() for checking TIF_SINGLESTEP
  usb: gadget: udc: gr_udc: fix memleak on error handling path in gr_ep_init()
  Input: synaptics - enable InterTouch for ThinkPad X1E 1st gen
  dmaengine: ioat setting ioat timeout as module parameter
  hwmon: (aspeed-pwm-tacho) Avoid possible buffer overflow
  regmap: dev_get_regmap_match(): fix string comparison
  spi: mediatek: use correct SPI_CFG2_REG MACRO
  Input: add `SW_MACHINE_COVER`
  dmaengine: tegra210-adma: Fix runtime PM imbalance on error
  HID: apple: Disable Fn-key key-re-mapping on clone keyboards
  HID: i2c-hid: add Mediacom FlexBook edge13 to descriptor override
  scripts/decode_stacktrace: strip basepath from all paths
  serial: exar: Fix GPIO configuration for Sealevel cards based on XR17V35X
  bonding: check return value of register_netdevice() in bond_newlink()
  i2c: rcar: always clear ICSAR to avoid side effects
  ipvs: fix the connection sync failed in some cases
  mlxsw: destroy workqueue when trap_register in mlxsw_emad_init
  bonding: check error value of register_netdevice() immediately
  net: smc91x: Fix possible memory leak in smc_drv_probe()
  drm: sun4i: hdmi: Fix inverted HPD result
  net: dp83640: fix SIOCSHWTSTAMP to update the struct with actual configuration
  ax88172a: fix ax88172a_unbind() failures
  hippi: Fix a size used in a 'pci_free_consistent()' in an error handling path
  bnxt_en: Fix race when modifying pause settings.
  btrfs: fix page leaks after failure to lock page for delalloc
  btrfs: fix mount failure caused by race with umount
  btrfs: fix double free on ulist after backref resolution failure
  ASoC: rt5670: Correct RT5670_LDO_SEL_MASK
  ALSA: info: Drop WARN_ON() from buffer NULL sanity check
  uprobes: Change handle_swbp() to send SIGTRAP with si_code=SI_KERNEL, to fix GDB regression
  IB/umem: fix reference count leak in ib_umem_odp_get()
  spi: spi-fsl-dspi: Exit the ISR with IRQ_NONE when it's not ours
  SUNRPC reverting d03727b248d0 ("NFSv4 fix CLOSE not waiting for direct IO compeletion")
  irqdomain/treewide: Keep firmware node unconditionally allocated
  drm/nouveau/i2c/g94-: increase NV_PMGR_DP_AUXCTL_TRANSACTREQ timeout
  net: sky2: initialize return of gm_phy_read
  drivers/net/wan/lapbether: Fixed the value of hard_header_len
  xtensa: update *pos in cpuinfo_op.next
  xtensa: fix __sync_fetch_and_{and,or}_4 declarations
  scsi: scsi_transport_spi: Fix function pointer check
  mac80211: allow rx of mesh eapol frames with default rx key
  pinctrl: amd: fix npins for uart0 in kerncz_groups
  gpio: arizona: put pm_runtime in case of failure
  gpio: arizona: handle pm_runtime_get_sync failure case
  ANDROID: Incremental fs: magic number compatible 32-bit
  ANDROID: kbuild: don't merge .*..compoundliteral in modules
  Revert "arm64/alternatives: use subsections for replacement sequences"
  Linux 4.14.189
  rxrpc: Fix trace string
  libceph: don't omit recovery_deletes in target_copy()
  x86/cpu: Move x86_cache_bits settings
  sched/fair: handle case of task_h_load() returning 0
  arm64: ptrace: Override SPSR.SS when single-stepping is enabled
  thermal/drivers/cpufreq_cooling: Fix wrong frequency converted from power
  misc: atmel-ssc: lock with mutex instead of spinlock
  dmaengine: fsl-edma: Fix NULL pointer exception in fsl_edma_tx_handler
  intel_th: pci: Add Emmitsburg PCH support
  intel_th: pci: Add Tiger Lake PCH-H support
  intel_th: pci: Add Jasper Lake CPU support
  hwmon: (emc2103) fix unable to change fan pwm1_enable attribute
  MIPS: Fix build for LTS kernel caused by backporting lpj adjustment
  timer: Fix wheel index calculation on last level
  uio_pdrv_genirq: fix use without device tree and no interrupt
  Input: i8042 - add Lenovo XiaoXin Air 12 to i8042 nomux list
  mei: bus: don't clean driver pointer
  Revert "zram: convert remaining CLASS_ATTR() to CLASS_ATTR_RO()"
  fuse: Fix parameter for FS_IOC_{GET,SET}FLAGS
  virtio: virtio_console: add missing MODULE_DEVICE_TABLE() for rproc serial
  USB: serial: option: add Quectel EG95 LTE modem
  USB: serial: option: add GosunCn GM500 series
  USB: serial: ch341: add new Product ID for CH340
  USB: serial: cypress_m8: enable Simply Automated UPB PIM
  USB: serial: iuu_phoenix: fix memory corruption
  usb: gadget: function: fix missing spinlock in f_uac1_legacy
  usb: chipidea: core: add wakeup support for extcon
  usb: dwc2: Fix shutdown callback in platform
  USB: c67x00: fix use after free in c67x00_giveback_urb
  ALSA: usb-audio: Fix race against the error recovery URB submission
  ALSA: line6: Perform sanity check for each URB creation
  HID: magicmouse: do not set up autorepeat
  mtd: rawnand: oxnas: Release all devices in the _remove() path
  mtd: rawnand: oxnas: Unregister all devices on error
  mtd: rawnand: oxnas: Keep track of registered devices
  mtd: rawnand: brcmnand: fix CS0 layout
  perf stat: Zero all the 'ena' and 'run' array slot stats for interval mode
  copy_xstate_to_kernel: Fix typo which caused GDB regression
  ARM: dts: socfpga: Align L2 cache-controller nodename with dtschema
  Revert "thermal: mediatek: fix register index error"
  staging: comedi: verify array index is correct before using it
  usb: gadget: udc: atmel: fix uninitialized read in debug printk
  spi: spi-sun6i: sun6i_spi_transfer_one(): fix setting of clock rate
  arm64: dts: meson: add missing gxl rng clock
  phy: sun4i-usb: fix dereference of pointer phy0 before it is null checked
  iio:health:afe4404 Fix timestamp alignment and prevent data leak.
  ACPI: video: Use native backlight on Acer TravelMate 5735Z
  ACPI: video: Use native backlight on Acer Aspire 5783z
  mmc: sdhci: do not enable card detect interrupt for gpio cd type
  doc: dt: bindings: usb: dwc3: Update entries for disabling SS instances in park mode
  Revert "usb/xhci-plat: Set PM runtime as active on resume"
  Revert "usb/ehci-platform: Set PM runtime as active on resume"
  Revert "usb/ohci-platform: Fix a warning when hibernating"
  of: of_mdio: Correct loop scanning logic
  net: dsa: bcm_sf2: Fix node reference count
  spi: fix initial SPI_SR value in spi-fsl-dspi
  spi: spi-fsl-dspi: Fix lockup if device is shutdown during SPI transfer
  iio:health:afe4403 Fix timestamp alignment and prevent data leak.
  iio:pressure:ms5611 Fix buffer element alignment
  iio: pressure: zpa2326: handle pm_runtime_get_sync failure
  iio: mma8452: Add missed iio_device_unregister() call in mma8452_probe()
  iio: magnetometer: ak8974: Fix runtime PM imbalance on error
  iio:humidity:hdc100x Fix alignment and data leak issues
  iio:magnetometer:ak8974: Fix alignment and data leak issues
  arm64/alternatives: don't patch up internal branches
  arm64: alternative: Use true and false for boolean values
  i2c: eg20t: Load module automatically if ID matches
  gfs2: read-only mounts should grab the sd_freeze_gl glock
  tpm_tis: extra chip->ops check on error path in tpm_tis_core_init
  arm64/alternatives: use subsections for replacement sequences
  drm/exynos: fix ref count leak in mic_pre_enable
  cgroup: Fix sock_cgroup_data on big-endian.
  cgroup: fix cgroup_sk_alloc() for sk_clone_lock()
  tcp: md5: do not send silly options in SYNCOOKIES
  tcp: make sure listeners don't initialize congestion-control state
  net_sched: fix a memory leak in atm_tc_init()
  tcp: md5: allow changing MD5 keys in all socket states
  tcp: md5: refine tcp_md5_do_add()/tcp_md5_hash_key() barriers
  tcp: md5: add missing memory barriers in tcp_md5_do_add()/tcp_md5_hash_key()
  net: usb: qmi_wwan: add support for Quectel EG95 LTE modem
  net: Added pointer check for dst->ops->neigh_lookup in dst_neigh_lookup_skb
  llc: make sure applications use ARPHRD_ETHER
  l2tp: remove skb_dst_set() from l2tp_xmit_skb()
  ipv4: fill fl4_icmp_{type,code} in ping_v4_sendmsg
  genetlink: remove genl_bind
  s390/mm: fix huge pte soft dirty copying
  ARC: elf: use right ELF_ARCH
  ARC: entry: fix potential EFA clobber when TIF_SYSCALL_TRACE
  dm: use noio when sending kobject event
  drm/radeon: fix double free
  btrfs: fix fatal extent_buffer readahead vs releasepage race
  Revert "ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb"
  KVM: x86: Mark CR4.TSD as being possibly owned by the guest
  KVM: x86: Inject #GP if guest attempts to toggle CR4.LA57 in 64-bit mode
  KVM: x86: bit 8 of non-leaf PDPEs is not reserved
  KVM: arm64: Stop clobbering x0 for HVC_SOFT_RESTART
  KVM: arm64: Fix definition of PAGE_HYP_DEVICE
  ALSA: usb-audio: add quirk for MacroSilicon MS2109
  ALSA: hda - let hs_mic be picked ahead of hp_mic
  ALSA: opl3: fix infoleak in opl3
  mlxsw: spectrum_router: Remove inappropriate usage of WARN_ON()
  net: macb: mark device wake capable when "magic-packet" property present
  bnxt_en: fix NULL dereference in case SR-IOV configuration fails
  nbd: Fix memory leak in nbd_add_socket
  arm64: kgdb: Fix single-step exception handling oops
  ALSA: compress: fix partial_drain completion state
  smsc95xx: avoid memory leak in smsc95xx_bind
  smsc95xx: check return value of smsc95xx_reset
  net: cxgb4: fix return error value in t4_prep_fw
  x86/entry: Increase entry_stack size to a full page
  nvme-rdma: assign completion vector correctly
  scsi: mptscsih: Fix read sense data size
  ARM: imx6: add missing put_device() call in imx6q_suspend_init()
  cifs: update ctime and mtime during truncate
  s390/kasan: fix early pgm check handler execution
  ixgbe: protect ring accesses with READ- and WRITE_ONCE
  spi: spidev: fix a potential use-after-free in spidev_release()
  spi: spidev: fix a race between spidev_release and spidev_remove
  gpu: host1x: Detach driver on unregister
  ARM: dts: omap4-droid4: Fix spi configuration and increase rate
  spi: spi-fsl-dspi: Fix external abort on interrupt in resume or exit paths
  spi: spi-fsl-dspi: use IRQF_SHARED mode to request IRQ
  spi: spi-fsl-dspi: Fix lockup if device is removed during SPI transfer
  spi: spi-fsl-dspi: Adding shutdown hook
  KVM: s390: reduce number of IO pins to 1
  UPSTREAM: perf/core: Fix crash when using HW tracing kernel filters
  ANDROID: fscrypt: fix DUN contiguity with inline encryption + IV_INO_LBLK_32 policies
  ANDROID: f2fs: add back compress inode check
  Linux 4.14.188
  efi: Make it possible to disable efivar_ssdt entirely
  dm zoned: assign max_io_len correctly
  irqchip/gic: Atomically update affinity
  MIPS: Add missing EHB in mtc0 -> mfc0 sequence for DSPen
  cifs: Fix the target file was deleted when rename failed.
  SMB3: Honor persistent/resilient handle flags for multiuser mounts
  SMB3: Honor 'seal' flag for multiuser mounts
  Revert "ALSA: usb-audio: Improve frames size computation"
  nfsd: apply umask on fs without ACL support
  i2c: algo-pca: Add 0x78 as SCL stuck low status for PCA9665
  virtio-blk: free vblk-vqs in error path of virtblk_probe()
  drm: sun4i: hdmi: Remove extra HPD polling
  hwmon: (acpi_power_meter) Fix potential memory leak in acpi_power_meter_add()
  hwmon: (max6697) Make sure the OVERT mask is set correctly
  cxgb4: parse TC-U32 key values and masks natively
  cxgb4: use unaligned conversion for fetching timestamp
  crypto: af_alg - fix use-after-free in af_alg_accept() due to bh_lock_sock()
  kgdb: Avoid suspicious RCU usage warning
  usb: usbtest: fix missing kfree(dev->buf) in usbtest_disconnect
  mm/slub: fix stack overruns with SLUB_STATS
  mm/slub.c: fix corrupted freechain in deactivate_slab()
  usbnet: smsc95xx: Fix use-after-free after removal
  EDAC/amd64: Read back the scrub rate PCI register on F15h
  mm: fix swap cache node allocation mask
  btrfs: fix data block group relocation failure due to concurrent scrub
  btrfs: cow_file_range() num_bytes and disk_num_bytes are same
  btrfs: fix a block group ref counter leak after failure to remove block group
  UPSTREAM: binder: fix null deref of proc->context

Change-Id: Ied6e98ddbfe44bcfedddcc76183ee5d8c5d240c9
Signed-off-by: Praneeth Bajjuri <praneeth@ti.com>
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 2015ae3..71d7296 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -320,7 +320,7 @@
 
 # Build the DT binary blobs if we have OF configured
 ifeq ($(CONFIG_USE_OF),y)
-KBUILD_DTBS := dtbs itbs
+KBUILD_DTBS := dtbs
 endif
 
 all:	$(notdir $(KBUILD_IMAGE)) $(KBUILD_DTBS)
@@ -360,7 +360,7 @@
 
 PHONY += dtbs dtbs_install itbs_install
 
-dtbs: prepare scripts
+dtbs: prepare scripts zImage
 	$(Q)$(MAKE) $(build)=$(boot)/dts
 
 itbs: prepare scripts zImage
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
index 545b1d8..ff74e31 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
@@ -13,7 +13,6 @@
 #include "dra74-ipu-dsp-common.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include "dra7xx-android-fstab.dtsi"
 
 / {
 	compatible = "ti,am572x-beagle-x15", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7";
diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi
index 9464045..3e8747f 100644
--- a/arch/arm/boot/dts/am57xx-idk-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi
@@ -7,7 +7,6 @@
  */
 
 #include "am57xx-industrial-grade.dtsi"
-#include "dra7xx-android-fstab.dtsi"
 
 / {
 	aliases {
diff --git a/arch/arm/boot/dts/dra7-evm-common.dtsi b/arch/arm/boot/dts/dra7-evm-common.dtsi
index 5ca6b66..4be0a0a 100644
--- a/arch/arm/boot/dts/dra7-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra7-evm-common.dtsi
@@ -10,7 +10,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/clk/ti-dra7-atl.h>
 #include <dt-bindings/input/input.h>
-#include "dra7xx-android-fstab.dtsi"
 
 / {
 	chosen {
diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi
index 64686cc..e467478 100644
--- a/arch/arm/boot/dts/dra72-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra72-evm-common.dtsi
@@ -11,7 +11,6 @@
 #include "dra7-ipu-dsp-common.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/clk/ti-dra7-atl.h>
-#include "dra7xx-android-fstab.dtsi"
 
 / {
 	compatible = "ti,dra72-evm", "ti,dra722", "ti,dra72", "ti,dra7";
diff --git a/arch/arm/boot/dts/dra7xx-android-fstab.dtsi b/arch/arm/boot/dts/dra7xx-android-fstab.dtsi
deleted file mode 100644
index b40822a..0000000
--- a/arch/arm/boot/dts/dra7xx-android-fstab.dtsi
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.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.
- */
-
-/ {
-	firmware {
-		android {
-			compatible = "android,firmware";
-			fstab {
-				compatible = "android,fstab";
-				system {
-					compatible = "android,system";
-					dev = "/dev/block/platform/44000000.ocp/480b4000.mmc/by-name/system";
-					type = "ext4";
-					mnt_flags = "ro";
-					fsmgr_flags = "wait";
-				};
-				vendor {
-					compatible = "android,vendor";
-					dev = "/dev/block/platform/44000000.ocp/480b4000.mmc/by-name/vendor";
-					type = "ext4";
-					mnt_flags = "ro";
-					fsmgr_flags = "wait";
-				};
-			};
-		};
-	};
-};
diff --git a/arch/arm/configs/ti_sdk_am57x_android_release_defconfig b/arch/arm/configs/ti_sdk_am57x_android_release_defconfig
new file mode 100644
index 0000000..fd941da
--- /dev/null
+++ b/arch/arm/configs/ti_sdk_am57x_android_release_defconfig
@@ -0,0 +1,895 @@
+CONFIG_KERNEL_LZMA=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_PROFILING=y
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_REFCOUNT_FULL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_CMDLINE_PARTITION=y
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_SOC_DRA7XX=y
+CONFIG_ARM_LPAE=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_DRA7XX=y
+CONFIG_PCI_DRA7XX_EP=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCI_ENDPOINT=y
+CONFIG_PCI_ENDPOINT_CONFIGFS=y
+CONFIG_PCI_EPF_TEST=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_KSM=y
+CONFIG_CMA=y
+CONFIG_SECCOMP=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CMDLINE="androidboot.selinux=permissive printk.devkmsg=on cma=256m vmalloc=400m"
+CONFIG_CMDLINE_EXTEND=y
+CONFIG_KEXEC=y
+CONFIG_EFI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPUFREQ_DT=y
+# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
+CONFIG_ARM_TI_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_KERNEL_MODE_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPVTI=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_UDP_DIAG=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_SOCKET_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_SOCKET_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_SCTP=m
+CONFIG_L2TP=y
+CONFIG_BRIDGE=m
+CONFIG_NET_DSA=m
+CONFIG_VLAN_8021Q=m
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_CLS_IND=y
+CONFIG_CAN=m
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+CONFIG_CAN_M_CAN=m
+CONFIG_CAN_RCAR=m
+CONFIG_CAN_MCP251X=m
+CONFIG_BT=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_RPMSG_PROTO=m
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=24
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_SIMPLE_PM_BUS=y
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_DENALI_DT=y
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_BCH=y
+CONFIG_MTD_NAND_BRCMNAND=y
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_SPI_CADENCE_QUADSPI=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_VIRTIO_BLK=y
+CONFIG_AD525X_DPOT=y
+CONFIG_AD525X_DPOT_I2C=y
+CONFIG_ICS932S401=y
+CONFIG_APDS9802ALS=y
+CONFIG_ISL29003=y
+CONFIG_SRAM=y
+CONFIG_PCI_ENDPOINT_TEST=m
+CONFIG_UID_SYS_STATS=y
+CONFIG_EEPROM_AT24=m
+CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_ATA=m
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+CONFIG_AHCI_DM816=m
+CONFIG_SATA_MV=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_VIRTIO_NET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+CONFIG_TIGON3=m
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_E1000=m
+CONFIG_E1000E=m
+# CONFIG_NET_VENDOR_I825XX is not set
+CONFIG_SKGE=m
+# CONFIG_NET_VENDOR_MELLANOX is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+CONFIG_TI_CPSW=y
+CONFIG_TI_CPTS=y
+CONFIG_TI_PRUETH=m
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+CONFIG_AT803X_PHY=y
+CONFIG_DP83848_PHY=y
+CONFIG_DP83867_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_ROCKCHIP_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPTP=y
+CONFIG_PPPOL2TP=y
+CONFIG_USB_NET_DRIVERS=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_B43=m
+CONFIG_BRCMFMAC=m
+CONFIG_IWLWIFI=m
+CONFIG_IWLDVM=m
+CONFIG_IWLMVM=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_RT2X00=m
+CONFIG_RT2800USB=m
+CONFIG_WL18XX=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_MATRIX=m
+CONFIG_KEYBOARD_SAMSUNG=m
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_GOODIX=m
+CONFIG_TOUCHSCREEN_MMS114=m
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
+CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_GPIO_DECODER=m
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+CONFIG_INPUT_ADXL34X=m
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=10
+CONFIG_SERIAL_8250_RUNTIME_UARTS=10
+CONFIG_SERIAL_8250_OMAP=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_BCM63XX=y
+CONFIG_SERIAL_BCM63XX_CONSOLE=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=m
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_MUX_PINCTRL=y
+CONFIG_I2C_DEMUX_PINCTRL=y
+CONFIG_I2C_EMEV2=m
+CONFIG_I2C_SLAVE_EEPROM=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=m
+CONFIG_SPI_OMAP24XX=y
+CONFIG_SPI_TI_QSPI=y
+CONFIG_SPMI=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_PINCTRL_PALMAS=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SYSCON=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_PCF857X=y
+CONFIG_GPIO_TPIC2810=m
+CONFIG_GPIO_PALMAS=y
+CONFIG_GPIO_TPS65910=y
+CONFIG_GPIO_PISOSR=m
+CONFIG_W1=m
+CONFIG_HDQ_MASTER_OMAP=m
+CONFIG_POWER_AVS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_BATTERY_ACT8945A=y
+CONFIG_BATTERY_SBS=y
+CONFIG_BATTERY_MAX17040=m
+CONFIG_BATTERY_MAX17042=m
+CONFIG_CHARGER_TPS65090=y
+CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_LM90=y
+CONFIG_SENSORS_LM95245=y
+CONFIG_SENSORS_NTC_THERMISTOR=m
+CONFIG_SENSORS_PWM_FAN=m
+CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_TMP102=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_FAIR_SHARE=y
+CONFIG_THERMAL_GOV_BANG_BANG=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
+CONFIG_CPU_THERMAL=y
+CONFIG_THERMAL_EMULATION=y
+CONFIG_TI_SOC_THERMAL=y
+CONFIG_TI_THERMAL=y
+CONFIG_DRA752_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=m
+CONFIG_BCMA=y
+CONFIG_BCMA_HOST_SOC=y
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
+CONFIG_BCMA_DRIVER_GPIO=y
+CONFIG_MFD_ACT8945A=y
+CONFIG_MFD_TI_AM335X_TSCADC=m
+CONFIG_MFD_PALMAS=y
+CONFIG_MFD_TPS65090=y
+CONFIG_MFD_TPS65217=y
+CONFIG_MFD_TI_LP873X=y
+CONFIG_MFD_TI_LP87565=y
+CONFIG_MFD_TPS65218=y
+CONFIG_MFD_TPS6586X=y
+CONFIG_MFD_TPS65910=y
+CONFIG_TWL6040_CORE=y
+CONFIG_REGULATOR_ACT8945A=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_LP873X=y
+CONFIG_REGULATOR_LP87565=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_REGULATOR_PBIAS=y
+CONFIG_REGULATOR_TI_ABB=y
+CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_REGULATOR_TPS65217=y
+CONFIG_REGULATOR_TPS65218=y
+CONFIG_REGULATOR_TPS6524X=y
+CONFIG_REGULATOR_TPS6586X=y
+CONFIG_REGULATOR_TPS65910=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_GSPCA=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_VIDEO_TI_CAL=m
+CONFIG_VIDEO_TI_VIP=m
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_TI_VPE=m
+CONFIG_V4L_TEST_DRIVERS=y
+CONFIG_VIDEO_VIVID=m
+# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
+CONFIG_VIDEO_ADV7180=m
+CONFIG_VIDEO_ML86V7667=m
+CONFIG_VIDEO_OV2659=m
+CONFIG_VIDEO_OV1063X=m
+CONFIG_VIDEO_OV490=m
+CONFIG_VIDEO_MT9T11X=m
+# CONFIG_VGA_ARB is not set
+CONFIG_DRM=y
+CONFIG_DRM_I2C_NXP_TDA998X=y
+CONFIG_DRM_OMAP=y
+CONFIG_DRM_OMAP_WB=y
+CONFIG_OMAP2_DSS_DEBUGFS=y
+# CONFIG_OMAP2_DSS_VENC is not set
+CONFIG_OMAP5_DSS_HDMI=y
+CONFIG_TI_DSS6=y
+CONFIG_DRM_OMAP_ENCODER_TFP410=y
+CONFIG_DRM_OMAP_ENCODER_TPD12S015=y
+CONFIG_DRM_OMAP_DRA7EVM_ENCODER_TPD12S015=y
+CONFIG_DRM_OMAP_ENCODER_TC358768=y
+CONFIG_DRM_OMAP_ENCODER_SII9022=y
+CONFIG_DRM_OMAP_CONNECTOR_DVI=y
+CONFIG_DRM_OMAP_CONNECTOR_HDMI=y
+CONFIG_DRM_OMAP_PANEL_DPI=y
+CONFIG_DRM_TILCDC=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_DRM_TOSHIBA_TC358767=y
+CONFIG_DRM_TIDSS=y
+# CONFIG_DRM_TIDSS_DSS6 is not set
+CONFIG_DRM_LEGACY=y
+CONFIG_PVR_SGX544=m
+CONFIG_FB_SSD1307=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_GPIO=y
+CONFIG_BACKLIGHT_LED=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_PCI is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_SOC=y
+CONFIG_SND_EDMA_SOC=y
+CONFIG_SND_DAVINCI_SOC_MCASP=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_HDMI_AUDIO=m
+CONFIG_SND_SOC_TI_MCASP=y
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_TLV320AIC31XX=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SIMPLE_CARD=m
+CONFIG_SND_SIMPLE_SCU_CARD=m
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_PRODIKEYS=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_HOLTEK=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PRIMAX=y
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SPEEDLINK=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_MUSB_HDRC=m
+CONFIG_USB_MUSB_OMAP2PLUS=m
+CONFIG_USB_MUSB_AM35X=m
+CONFIG_USB_MUSB_DSPS=m
+CONFIG_USB_TI_CPPI41_DMA=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_TEST=m
+CONFIG_NOP_USB_XCEIV=m
+CONFIG_AM335X_PHY_USB=m
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_ISP1301=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=32
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_UVC=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_G_WEBCAM=m
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
+CONFIG_MMC_SDHCI_OF_AT91=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SDHCI_OMAP=y
+CONFIG_LEDS_CLASS_FLASH=m
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TLC591XX=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_EDAC=y
+CONFIG_EDAC_TI=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DEBUG=y
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_PALMAS=m
+CONFIG_RTC_DRV_TPS6586X=m
+CONFIG_RTC_DRV_TPS65910=m
+CONFIG_RTC_DRV_EFI=m
+CONFIG_RTC_DRV_OMAP=m
+CONFIG_DMADEVICES=y
+CONFIG_FSL_EDMA=y
+CONFIG_DW_DMAC=y
+CONFIG_TI_CPPI41=y
+CONFIG_SW_SYNC=y
+CONFIG_UIO=m
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ION=y
+CONFIG_STAGING_BOARD=y
+CONFIG_COMMON_CLK_PALMAS=y
+CONFIG_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_OMAP=y
+CONFIG_OMAP_IOMMU=y
+CONFIG_OMAP_IOMMU_DEBUG=y
+CONFIG_REMOTEPROC=y
+CONFIG_OMAP_REMOTEPROC=y
+CONFIG_PRUSS_REMOTEPROC=m
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_RPMSG_RPC=y
+CONFIG_RPMSG_PRU=m
+CONFIG_SOC_TI=y
+CONFIG_EXTCON_PALMAS=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_IIO_SW_TRIGGER=y
+CONFIG_TI_AM335X_ADC=m
+CONFIG_VF610_ADC=m
+CONFIG_MPU3050_I2C=y
+CONFIG_CM36651=m
+CONFIG_SENSORS_ISL29018=y
+CONFIG_SENSORS_ISL29028=y
+CONFIG_AK8975=y
+CONFIG_IIO_HRTIMER_TRIGGER=y
+CONFIG_PWM_FSL_FTM=m
+CONFIG_PWM_TIECAP=y
+CONFIG_PWM_TIEHRPWM=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_TI_SYSCON=y
+CONFIG_OMAP_USB2=y
+CONFIG_TI_PIPE3=y
+CONFIG_PHY_AM654_MMC=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+# CONFIG_DMIID is not set
+CONFIG_EFI_VARS=m
+CONFIG_EFI_CAPSULE_LOADER=m
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_SDCARD_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_CONSOLE=y
+CONFIG_PSTORE_PMSG=y
+CONFIG_PSTORE_RAM=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_ACL=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_KEYS=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_CRYPTO_USER=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
+CONFIG_CRYPTO_DEV_OMAP=m
+CONFIG_CRYPTO_DEV_OMAP_SHAM=m
+CONFIG_CRYPTO_DEV_OMAP_AES=m
+CONFIG_CRYPTO_DEV_OMAP_DES=m
+CONFIG_ARM_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM_NEON=m
+CONFIG_CRYPTO_SHA1_ARM_CE=m
+CONFIG_CRYPTO_SHA2_ARM_CE=m
+CONFIG_CRYPTO_SHA512_ARM=m
+CONFIG_CRYPTO_AES_ARM=m
+CONFIG_CRYPTO_AES_ARM_BS=m
+CONFIG_CRYPTO_AES_ARM_CE=m
+CONFIG_CRYPTO_GHASH_ARM_CE=m
+CONFIG_CRYPTO_CRC32_ARM_CE=m
+CONFIG_CRYPTO_CHACHA20_NEON=m
diff --git a/build.config b/build.config
new file mode 100644
index 0000000..826f603
--- /dev/null
+++ b/build.config
@@ -0,0 +1,28 @@
+CONFIG_PATH=$(realpath ${BASH_SOURCE[0]})
+OMAP_KERNEL_DIR=$(dirname ${CONFIG_PATH})
+OMAP_KERNEL_DIR=${OMAP_KERNEL_DIR##${ROOT_DIR}/}
+
+. ${ROOT_DIR}/${OMAP_KERNEL_DIR}/build.config.common
+
+KERNEL_DIR=${OMAP_KERNEL_DIR}
+
+ARCH=arm
+BRANCH=android-beagle-x15-4.14
+CLANG_TRIPLE=arm-linux-gnueabi-
+CROSS_COMPILE=arm-linux-androidkernel-
+DEFCONFIG=ti_sdk_am57x_android_release_defconfig
+EXTRA_CMDS=''
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin
+
+BUILDTOOLS_PREBUILT_BIN=''
+IN_KERNEL_MODULES=1
+DO_NOT_STRIP_MODULES=1
+
+FILES="
+arch/arm/boot/zImage
+arch/arm/boot/dts/ti/am57xx-beagle-x15-revc.dtb
+arch/arm/boot/dts/ti/am57xx-evm-common.dtbo
+arch/arm/boot/dts/ti/am57xx-evm-reva3.dtbo
+vmlinux
+System.map
+"
diff --git a/build.config.net_test b/build.config.net_test
new file mode 100644
index 0000000..c0dec17
--- /dev/null
+++ b/build.config.net_test
@@ -0,0 +1,9 @@
+ARCH=um
+SUBARCH=x86_64
+CROSS_COMPILE=
+EXTRA_CMDS=''
+KERNEL_DIR=omap
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=
+FILES="
+linux
+"
diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index 99251b5..1b35f59 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -4,4 +4,5 @@
 obj-$(CONFIG_TEGRA_HOST1X)	+= host1x/
 obj-y			+= drm/ vga/
 obj-$(CONFIG_IMX_IPUV3_CORE)	+= ipu-v3/
+obj-$(CONFIG_PVR_SGX544)	+= pvr/
 obj-$(CONFIG_TRACE_GPU_MEM)		+= trace/
diff --git a/drivers/gpu/pvr/Kconfig b/drivers/gpu/pvr/Kconfig
new file mode 100644
index 0000000..dbb433a
--- /dev/null
+++ b/drivers/gpu/pvr/Kconfig
@@ -0,0 +1,7 @@
+config PVR_SGX544
+	tristate "PowerVR SGX544"
+	depends on PREEMPT
+	depends on SYNC_FILE
+	default n
+	help
+	  Support for the PowerVR SGX544 3D core
diff --git a/drivers/gpu/pvr/Makefile b/drivers/gpu/pvr/Makefile
new file mode 100644
index 0000000..533c131
--- /dev/null
+++ b/drivers/gpu/pvr/Makefile
@@ -0,0 +1,66 @@
+ccflags-y += \
+	-D__linux__ \
+	-include $(srctree)/drivers/gpu/pvr/config_kernel.h \
+	-Idrivers/gpu/pvr/include4 \
+	-Idrivers/gpu/pvr/services4/include \
+	-Idrivers/gpu/pvr/services4/system/omap \
+	-Idrivers/gpu/pvr/services4/system/include \
+	-Idrivers/gpu/pvr/services4/srvkm/bridged \
+	-Idrivers/gpu/pvr/services4/srvkm/bridged/sgx \
+	-Idrivers/gpu/pvr/services4/srvkm/common \
+	-Idrivers/gpu/pvr/services4/srvkm/devices/sgx \
+	-Idrivers/gpu/pvr/services4/srvkm/env/linux \
+	-Idrivers/gpu/pvr/services4/srvkm/include \
+	-Idrivers/gpu/pvr/services4/srvkm/hwdefs
+
+pvrsrvkm-y += \
+	services4/srvkm/bridged/bridged_pvr_bridge.o \
+	services4/srvkm/bridged/bridged_support.o \
+	services4/srvkm/bridged/sgx/bridged_sgx_bridge.o \
+	services4/srvkm/common/buffer_manager.o \
+	services4/srvkm/common/devicemem.o \
+	services4/srvkm/common/handle.o \
+	services4/srvkm/common/hash.o \
+	services4/srvkm/common/lists.o \
+	services4/srvkm/common/mem.o \
+	services4/srvkm/common/mem_debug.o \
+	services4/srvkm/common/metrics.o \
+	services4/srvkm/common/osfunc_common.o \
+	services4/srvkm/common/pdump_common.o \
+	services4/srvkm/common/perproc.o \
+	services4/srvkm/common/power.o \
+	services4/srvkm/common/pvrsrv.o \
+	services4/srvkm/common/ra.o \
+	services4/srvkm/common/refcount.o \
+	services4/srvkm/common/resman.o \
+	services4/srvkm/devices/sgx/mmu.o \
+	services4/srvkm/devices/sgx/pb.o \
+	services4/srvkm/devices/sgx/sgxinit.o \
+	services4/srvkm/devices/sgx/sgxkick.o \
+	services4/srvkm/devices/sgx/sgxpower.o \
+	services4/srvkm/devices/sgx/sgxreset.o \
+	services4/srvkm/devices/sgx/sgxtransfer.o \
+	services4/srvkm/devices/sgx/sgxutils.o \
+	services4/srvkm/env/linux/dmabuf.o \
+	services4/srvkm/env/linux/dma_fence_sync_native_server.o \
+	services4/srvkm/env/linux/event.o \
+	services4/srvkm/env/linux/mmap.o \
+	services4/srvkm/env/linux/mm.o \
+	services4/srvkm/env/linux/module.o \
+	services4/srvkm/env/linux/mutex.o \
+	services4/srvkm/env/linux/mutils.o \
+	services4/srvkm/env/linux/osfunc.o \
+	services4/srvkm/env/linux/osperproc.o \
+	services4/srvkm/env/linux/pdump.o \
+	services4/srvkm/env/linux/proc.o \
+	services4/srvkm/env/linux/pvr_bridge_k.o \
+	services4/srvkm/env/linux/pvr_counting_timeline.o \
+	services4/srvkm/env/linux/pvr_debug.o \
+	services4/srvkm/env/linux/pvr_fence.o \
+	services4/srvkm/env/linux/pvr_linux_fence.o \
+	services4/srvkm/env/linux/pvr_sw_fence.o \
+	services4/srvkm/env/linux/pvr_sync_common.o \
+	services4/system/omap/sysconfig.o \
+	services4/system/omap/sysutils.o \
+
+obj-$(CONFIG_PVR_SGX544) += pvrsrvkm.o
diff --git a/drivers/gpu/pvr/config_kernel.h b/drivers/gpu/pvr/config_kernel.h
new file mode 100644
index 0000000..3d48cea
--- /dev/null
+++ b/drivers/gpu/pvr/config_kernel.h
@@ -0,0 +1,53 @@
+#define SGX_FEATURE_MP_CORE_COUNT 2
+#define LINUX
+#define PVR_BUILD_DIR "omap_android"
+#define PVR_BUILD_TYPE "release"
+#define PVRSRV_MODNAME "pvrsrvkm"
+#define SGXCORE 544
+#define SGX544
+#define SUPPORT_SGX544
+#define SUPPORT_SGX
+#define SGX_CORE_REV 116
+#define TRANSFER_QUEUE
+#define PVR_SECURE_HANDLES
+#define SUPPORT_LISR_MISR_SYNC
+#define PVR_LINUX_MEM_AREA_POOL_MAX_PAGES 10800
+#define PVR_LINUX_MEM_AREA_USE_VMAP
+#define PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK
+#define RELEASE
+#define SUPPORT_PERCONTEXT_PB
+#define SUPPORT_HW_RECOVERY
+#define SUPPORT_SGX_HWPERF
+#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING
+#define SUPPORT_MEMINFO_IDS
+#define SUPPORT_SGX_NEW_STATUS_VALS
+#define SUPPORT_DBGDRV_EVENT_OBJECTS
+#define SGX_FEATURE_SYSTEM_CACHE
+#define SGX_FEATURE_MP
+#define SYS_USING_INTERRUPTS
+#define PVRSRV_NEW_PVR_DPF
+#define PVRSRV_NEED_PVR_DPF
+#define SUPPORT_DMABUF
+#define IMG_ADDRSPACE_PHYSADDR_BITS 32
+#define SUPPORT_LINUX_X86_WRITECOMBINE
+#define SUPPORT_LINUX_X86_PAT
+#define SGX_DYNAMIC_TIMING_INFO
+#define SYS_CUSTOM_POWERLOCK_WRAP
+#define PVR_LINUX_USING_WORKQUEUES
+#define PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE
+#define PVR_LINUX_TIMERS_USING_WORKQUEUES
+#define LDM_PLATFORM
+#define PVR_LDM_DEVICE_TREE
+#define PVR_LDM_PLATFORM_PRE_REGISTERED
+#define PVR_LDM_PLATFORM_PRE_REGISTERED_DEV "pvrsrvkm"
+#define PVR_LDM_DRIVER_REGISTRATION_NAME "pvrsrvkm"
+#define SUPPORT_LARGE_GENERAL_HEAP
+#define ANDROID
+#define PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE
+#define SUPPORT_ION_HEADER "../drivers/staging/android/ion/ion.h"
+#define SUPPORT_ION_PRIV_HEADER "../drivers/staging/android/ion/ion_priv.h"
+#define SUPPORT_ION_USE_SG_LENGTH
+#define PVR_NO_OMAP_TIMER
+#define VS_PRODUCT_VERSION 5
+#define SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED
+#define SUPPORT_TI_VERSION_STRING
diff --git a/drivers/gpu/pvr/include4/dbgdrvif.h b/drivers/gpu/pvr/include4/dbgdrvif.h
new file mode 100644
index 0000000..b5edb5a
--- /dev/null
+++ b/drivers/gpu/pvr/include4/dbgdrvif.h
@@ -0,0 +1,382 @@
+/*************************************************************************/ /*!
+@Title          Debug driver
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Debug Driver Interface
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _DBGDRVIF_
+#define _DBGDRVIF_
+
+
+#if defined(__linux__)
+
+#define FILE_DEVICE_UNKNOWN             0
+#define METHOD_BUFFERED                 0
+#define FILE_ANY_ACCESS                 0
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) (Function) 
+#define MAKEIOCTLINDEX(i)	((i) & 0xFFF)
+
+#else
+
+#include "ioctldef.h"
+
+#endif
+
+/*****************************************************************************
+ Stream mode stuff.
+*****************************************************************************/
+#define DEBUG_CAPMODE_FRAMED			0x00000001UL
+#define DEBUG_CAPMODE_CONTINUOUS		0x00000002UL
+#define DEBUG_CAPMODE_HOTKEY			0x00000004UL
+
+#define DEBUG_OUTMODE_STANDARDDBG		0x00000001UL
+#define DEBUG_OUTMODE_MONO				0x00000002UL
+#define DEBUG_OUTMODE_STREAMENABLE		0x00000004UL
+#define DEBUG_OUTMODE_ASYNC				0x00000008UL
+#define DEBUG_OUTMODE_SGXVGA            0x00000010UL
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM	0x00000001UL
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION	0x00000002UL
+#define DEBUG_FLAGS_ENABLESAMPLE		0x00000004UL
+#define DEBUG_FLAGS_READONLY			0x00000008UL
+#define DEBUG_FLAGS_WRITEONLY			0x00000010UL
+
+#define DEBUG_FLAGS_TEXTSTREAM			0x80000000UL
+
+/*****************************************************************************
+ Debug level control. Only bothered with the first 12 levels, I suspect you
+ get the idea...
+*****************************************************************************/
+#define DEBUG_LEVEL_0					0x00000001UL
+#define DEBUG_LEVEL_1					0x00000003UL
+#define DEBUG_LEVEL_2					0x00000007UL
+#define DEBUG_LEVEL_3					0x0000000FUL
+#define DEBUG_LEVEL_4					0x0000001FUL
+#define DEBUG_LEVEL_5					0x0000003FUL
+#define DEBUG_LEVEL_6					0x0000007FUL
+#define DEBUG_LEVEL_7					0x000000FFUL
+#define DEBUG_LEVEL_8					0x000001FFUL
+#define DEBUG_LEVEL_9					0x000003FFUL
+#define DEBUG_LEVEL_10					0x000007FFUL
+#define DEBUG_LEVEL_11					0x00000FFFUL
+
+#define DEBUG_LEVEL_SEL0				0x00000001UL
+#define DEBUG_LEVEL_SEL1				0x00000002UL
+#define DEBUG_LEVEL_SEL2				0x00000004UL
+#define DEBUG_LEVEL_SEL3				0x00000008UL
+#define DEBUG_LEVEL_SEL4				0x00000010UL
+#define DEBUG_LEVEL_SEL5				0x00000020UL
+#define DEBUG_LEVEL_SEL6				0x00000040UL
+#define DEBUG_LEVEL_SEL7				0x00000080UL
+#define DEBUG_LEVEL_SEL8				0x00000100UL
+#define DEBUG_LEVEL_SEL9				0x00000200UL
+#define DEBUG_LEVEL_SEL10				0x00000400UL
+#define DEBUG_LEVEL_SEL11				0x00000800UL
+
+/*****************************************************************************
+ IOCTL values.
+*****************************************************************************/
+#define DEBUG_SERVICE_IOCTL_BASE		0x800UL
+#define DEBUG_SERVICE_CREATESTREAM		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DESTROYSTREAM		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRING		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READSTRING		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE				CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ				CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGMODE		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGOUTMODE	CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGLEVEL		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0A, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETFRAME			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0B, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0C, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_OVERRIDEMODE		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0D, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DEFAULTMODE		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0E, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSERVICETABLE	CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0F, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE2			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRINGCM		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITECM			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_ISCAPTUREFRAME	CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITELF			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READLF			CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x17, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x18, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETCONNNOTIFY		CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x19, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+typedef enum _DBG_EVENT_
+{
+	DBG_EVENT_STREAM_DATA = 1
+} DBG_EVENT;
+
+
+/*****************************************************************************
+ In/Out Structures
+*****************************************************************************/
+typedef struct _DBG_IN_CREATESTREAM_
+{
+	union
+	{
+		IMG_CHAR *pszName;
+		IMG_UINT64 ui64Name;
+	} u;
+	IMG_UINT32 ui32Pages;
+	IMG_UINT32 ui32CapMode;
+	IMG_UINT32 ui32OutMode;
+}DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_IN_FINDSTREAM_
+{
+	union
+	{
+		IMG_CHAR *pszName;
+		IMG_UINT64 ui64Name;
+	}u;
+	IMG_BOOL bResetStream;
+}DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+typedef struct _DBG_IN_WRITESTRING_
+{
+	union
+	{
+		IMG_CHAR *pszString;
+		IMG_UINT64 ui64String;
+	} u;
+	IMG_SID hStream;
+	IMG_UINT32 ui32Level;
+}DBG_IN_WRITESTRING, *PDBG_IN_WRITESTRING;
+
+typedef struct _DBG_IN_READSTRING_
+{
+	union
+	{
+		IMG_CHAR *pszString;
+		IMG_UINT64 ui64String;
+	} u;
+	IMG_SID hStream;
+	IMG_UINT32 ui32StringLen;
+} DBG_IN_READSTRING, *PDBG_IN_READSTRING;
+
+typedef struct _DBG_IN_SETDEBUGMODE_
+{
+	IMG_SID hStream;
+	IMG_UINT32 ui32Mode;
+	IMG_UINT32 ui32Start;
+	IMG_UINT32 ui32End;
+	IMG_UINT32 ui32SampleRate;
+} DBG_IN_SETDEBUGMODE, *PDBG_IN_SETDEBUGMODE;
+
+typedef struct _DBG_IN_SETDEBUGOUTMODE_
+{
+	IMG_SID hStream;
+	IMG_UINT32 ui32Mode;
+} DBG_IN_SETDEBUGOUTMODE, *PDBG_IN_SETDEBUGOUTMODE;
+
+typedef struct _DBG_IN_SETDEBUGLEVEL_
+{
+	IMG_SID hStream;
+	IMG_UINT32 ui32Level;
+} DBG_IN_SETDEBUGLEVEL, *PDBG_IN_SETDEBUGLEVEL;
+
+typedef struct _DBG_IN_SETFRAME_
+{
+	IMG_SID hStream;
+	IMG_UINT32 ui32Frame;
+} DBG_IN_SETFRAME, *PDBG_IN_SETFRAME;
+
+typedef struct _DBG_IN_WRITE_
+{
+	union
+	{
+		IMG_UINT8 *pui8InBuffer;
+		IMG_UINT64 ui64InBuffer;
+	} u;
+	IMG_SID hStream;
+	IMG_UINT32 ui32Level;
+	IMG_UINT32 ui32TransferSize;
+} DBG_IN_WRITE, *PDBG_IN_WRITE;
+
+typedef struct _DBG_IN_READ_
+{
+	union
+	{
+		IMG_UINT8 *pui8OutBuffer;
+		IMG_UINT64 ui64OutBuffer;
+	} u;
+	IMG_SID hStream;
+	IMG_BOOL bReadInitBuffer;
+	IMG_UINT32 ui32OutBufferSize;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_IN_OVERRIDEMODE_
+{
+	IMG_SID hStream;
+	IMG_UINT32 ui32Mode;
+} DBG_IN_OVERRIDEMODE, *PDBG_IN_OVERRIDEMODE;
+
+typedef struct _DBG_IN_ISCAPTUREFRAME_
+{
+	IMG_SID hStream;
+	IMG_BOOL bCheckPreviousFrame;
+} DBG_IN_ISCAPTUREFRAME, *PDBG_IN_ISCAPTUREFRAME;
+
+typedef struct _DBG_IN_SETMARKER_
+{
+	IMG_SID hStream;
+	IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+typedef struct _DBG_IN_WRITE_LF_
+{
+	union
+	{
+		IMG_UINT8 *pui8InBuffer;
+		IMG_UINT64 ui64InBuffer;
+	} u;
+	IMG_UINT32 ui32Flags;
+	IMG_SID    hStream;
+	IMG_UINT32 ui32Level;
+	IMG_UINT32 ui32BufferSize;
+} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+
+/*
+	Flags for above struct
+*/
+#define WRITELF_FLAGS_RESETBUF		0x00000001UL
+
+/*
+	Common control structure (don't duplicate control in main stream
+	and init phase stream).
+*/
+typedef struct _DBG_STREAM_CONTROL_
+{
+	IMG_BOOL   bInitPhaseComplete;		/*!< init phase has finished */
+	IMG_UINT32 ui32Flags;			/*!< flags (see DEBUG_FLAGS above) */
+
+	IMG_UINT32 ui32CapMode;			/*!< capturing mode framed/hot key */
+	IMG_UINT32 ui32OutMode;			/*!< output mode, e.g. files */
+	IMG_UINT32 ui32DebugLevel;
+	IMG_UINT32 ui32DefaultMode;
+	IMG_UINT32 ui32Start;			/*!< first capture frame */
+	IMG_UINT32 ui32End;				/*!< last frame */
+	IMG_UINT32 ui32Current;			/*!< current frame */
+	IMG_UINT32 ui32SampleRate;		/*!< capture frequency */
+	IMG_UINT32 ui32Reserved;
+} DBG_STREAM_CONTROL, *PDBG_STREAM_CONTROL;
+/*
+	Per-buffer control structure.
+*/
+#define MAX_STREAM_NAME_LENGTH 30
+typedef struct _DBG_STREAM_
+{
+	struct _DBG_STREAM_ *psNext;
+	struct _DBG_STREAM_ *psInitStream;
+	DBG_STREAM_CONTROL *psCtrl;
+	IMG_BOOL   bCircularAllowed;
+	IMG_PVOID  pvBase;
+	IMG_UINT32 ui32Size;
+	IMG_UINT32 ui32RPtr;
+	IMG_UINT32 ui32WPtr;
+	IMG_UINT32 ui32DataWritten;
+	IMG_UINT32 ui32Marker;			/*!< marker for file splitting */
+	IMG_UINT32 ui32InitPhaseWOff;	/*!< snapshot offset for init phase end for follow-on pdump */
+	IMG_CHAR szName[MAX_STREAM_NAME_LENGTH];		/* Give this a size, some compilers don't like [] */
+} DBG_STREAM,*PDBG_STREAM;
+
+/*
+ * Allows dbgdrv to notify services when events happen, e.g. pdump.exe starts.
+ * (better than resetting psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0
+ * in SGXGetClientInfoKM.)
+ */
+typedef struct _DBGKM_CONNECT_NOTIFIER_
+{
+	IMG_VOID (IMG_CALLCONV *pfnConnectNotifier)		(IMG_VOID);
+} DBGKM_CONNECT_NOTIFIER, *PDBGKM_CONNECT_NOTIFIER;
+
+/*****************************************************************************
+ Kernel mode service table
+*****************************************************************************/
+typedef struct _DBGKM_SERVICE_TABLE_
+{
+	IMG_UINT32 ui32Size;
+	IMG_VOID * 	(IMG_CALLCONV *pfnCreateStream)			(IMG_CHAR * pszName,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32OutMode,IMG_UINT32 ui32Flags,IMG_UINT32 ui32Pages);
+	IMG_VOID 	(IMG_CALLCONV *pfnDestroyStream)		(PDBG_STREAM psStream);
+	IMG_VOID * 	(IMG_CALLCONV *pfnFindStream) 			(IMG_CHAR * pszName, IMG_BOOL bResetInitBuffer);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteString) 			(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+	IMG_UINT32 	(IMG_CALLCONV *pfnReadString)			(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteBIN)				(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+	IMG_UINT32 	(IMG_CALLCONV *pfnReadBIN)				(PDBG_STREAM psStream,IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetCaptureMode)		(PDBG_STREAM psStream,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetOutputMode)		(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetDebugLevel)		(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetFrame)				(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+	IMG_UINT32 	(IMG_CALLCONV *pfnGetFrame)				(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnOverrideMode)			(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+	IMG_VOID 	(IMG_CALLCONV *pfnDefaultMode)			(PDBG_STREAM psStream);
+	IMG_UINT32	(IMG_CALLCONV *pfnDBGDrivWrite2)		(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteStringCM)		(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+	IMG_UINT32	(IMG_CALLCONV *pfnWriteBINCM)			(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetMarker)			(PDBG_STREAM psStream,IMG_UINT32 ui32Marker);
+	IMG_UINT32 	(IMG_CALLCONV *pfnGetMarker)			(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnStartInitPhase)		(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnStopInitPhase)		(PDBG_STREAM psStream);
+	IMG_BOOL 	(IMG_CALLCONV *pfnIsCaptureFrame)		(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWriteLF)				(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+	IMG_UINT32 	(IMG_CALLCONV *pfnReadLF)				(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+	IMG_UINT32 	(IMG_CALLCONV *pfnGetStreamOffset)		(PDBG_STREAM psStream);
+	IMG_VOID	(IMG_CALLCONV *pfnSetStreamOffset)		(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+	IMG_BOOL 	(IMG_CALLCONV *pfnIsLastCaptureFrame)	(PDBG_STREAM psStream);
+	IMG_VOID 	(IMG_CALLCONV *pfnWaitForEvent)			(DBG_EVENT eEvent);
+	IMG_VOID 	(IMG_CALLCONV *pfnSetConnectNotifier)	(DBGKM_CONNECT_NOTIFIER fn_notifier);
+	IMG_UINT32 	(IMG_CALLCONV *pfnWritePersist)			(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+#if defined(__linux__)
+/*****************************************************************************
+ Function to export service table from debug driver to the PDUMP component.
+*****************************************************************************/
+IMG_VOID DBGDrvGetServiceTable(DBGKM_SERVICE_TABLE **fn_table);
+#endif
+
+
+#endif
+/*****************************************************************************
+ End of file (DBGDRVIF.H)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/include4/img_defs.h b/drivers/gpu/pvr/include4/img_defs.h
new file mode 100644
index 0000000..9350cf6
--- /dev/null
+++ b/drivers/gpu/pvr/include4/img_defs.h
@@ -0,0 +1,227 @@
+/*************************************************************************/ /*!
+@Title          Common header containing type definitions for portability
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Contains variable and structure definitions. Any platform
+                specific types should be defined in this file.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if !defined (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+typedef		enum	img_tag_TriStateSwitch
+{
+	IMG_ON		=	0x00,
+	IMG_OFF,
+	IMG_IGNORE
+
+} img_TriStateSwitch, * img_pTriStateSwitch;
+
+#define		IMG_SUCCESS				0
+
+#define		IMG_NO_REG				1
+
+#if defined (NO_INLINE_FUNCS)
+	#define	INLINE
+	#define	FORCE_INLINE
+#else
+#if defined (__cplusplus)
+	#define INLINE					inline
+	#define	FORCE_INLINE			inline
+#else
+#if	!defined(INLINE)
+	#define	INLINE					__inline
+#endif
+	#define	FORCE_INLINE			static __inline
+#endif
+#endif
+
+
+/* Use this in any file, or use attributes under GCC - see below */
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define	PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+/* The best way to supress unused parameter warnings using GCC is to use a
+ * variable attribute.  Place the unref__ between the type and name of an
+ * unused parameter in a function parameter list, eg `int unref__ var'. This
+ * should only be used in GCC build environments, for example, in files that
+ * compile only on Linux. Other files should use UNREFERENCED_PARAMETER */
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+/*
+	Wide character definitions
+*/
+#ifndef _TCHAR_DEFINED
+#if defined(UNICODE)
+typedef unsigned short		TCHAR, *PTCHAR, *PTSTR;
+#else	/* #if defined(UNICODE) */
+typedef char				TCHAR, *PTCHAR, *PTSTR;
+#endif	/* #if defined(UNICODE) */
+#define _TCHAR_DEFINED
+#endif /* #ifndef _TCHAR_DEFINED */
+
+
+			#if defined(__linux__) || defined(__QNXNTO__) || defined(__METAG)
+
+				#define IMG_CALLCONV
+				#define IMG_INTERNAL	__attribute__((visibility("hidden")))
+				#define IMG_EXPORT		__attribute__((visibility("default")))
+				#define IMG_IMPORT
+				#define IMG_RESTRICT	__restrict__
+			#if defined(USE_64BIT_COMPAT)
+				#define IMG_COMPAT __attribute__ ((packed))
+			#else
+				#define IMG_COMPAT
+			#endif
+
+			#else
+					#error("define an OS")
+			#endif
+
+// Use default definition if not overridden
+#ifndef IMG_ABORT
+	#define IMG_ABORT()	abort()
+#endif
+
+#ifndef IMG_MALLOC
+	#define IMG_MALLOC(A)		malloc	(A)
+#endif
+
+#ifndef IMG_FREE
+	#define IMG_FREE(A)			free	(A)
+#endif
+
+#define IMG_CONST const
+
+#if defined(__GNUC__)
+#define IMG_FORMAT_PRINTF(x,y)		__attribute__((format(printf,x,y)))
+#else
+#define IMG_FORMAT_PRINTF(x,y)
+#endif
+
+/*
+ * Cleanup request defines
+  */
+#define  CLEANUP_WITH_POLL		IMG_FALSE
+#define  FORCE_CLEANUP			IMG_TRUE
+
+#if defined (_WIN64)
+#define IMG_UNDEF	(~0ULL)
+#else
+#define IMG_UNDEF	(~0UL)
+#endif
+
+/*
+   Do the right thing when using printf to output cpu addresses,
+   depending on architecture.
+ */
+#if defined (_WIN64)
+    #define UINTPTR_FMT "%016llX"
+#else
+    #if defined (__x86_64__)
+        #define UINTPTR_FMT "%016lX"
+    #else
+        #define UINTPTR_FMT "%08lX"
+    #endif
+#endif
+
+/* 
+   Similarly for DEV_ and SYS_ PHYSADDRs, but this is dependent on 32/36-bit MMU
+   capability, in addition to host architecture.
+ */
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+	#if defined(IMG_UINT32_IS_ULONG)
+		#define CPUPADDR_FMT "%08lX"
+		#define DEVPADDR_FMT "%08lX"
+		#define SYSPADDR_FMT "%08lX"
+	#else
+		#define CPUPADDR_FMT "%08X"
+		#define DEVPADDR_FMT "%08X"
+		#define SYSPADDR_FMT "%08X"
+	#endif
+#else
+	#if defined(__x86_64__)
+			#define CPUPADDR_FMT "%016lX"
+			#define DEVPADDR_FMT "%016lX"
+			#define SYSPADDR_FMT "%016lX"
+	#else
+
+			#define CPUPADDR_FMT "%016llX"
+			#define DEVPADDR_FMT "%016llX"
+			#define SYSPADDR_FMT "%016llX"
+	#endif
+#endif
+
+/*
+   Define a printf format macro for the length property of the format-specifier
+   for size_t, that allows avoidance of C99 dependency on compilers that don't
+   support this, while still ensuring that whatever the size of size_t (eg 32, 
+   64 bit Linux builds, or Win32/64 builds), a size_t (or IMG_SIZE_T) can be
+   passed to printf-type functions without a cast.
+*/
+#if defined LINUX
+	/* Use C99 format specifier where possible */
+	#define SIZE_T_FMT_LEN "z"
+#elif  defined _WIN64
+	#define SIZE_T_FMT_LEN "I"
+#else
+	#define SIZE_T_FMT_LEN "l" /* May need to be updated as required, for other OSs */
+#endif
+
+
+#if defined (__x86_64__)
+	#define IMG_UINT64_FMT "l"
+#else
+	#define IMG_UINT64_FMT "ll" /* May need to be updated as required, for other OSs */
+#endif
+
+/*
+	Some versions of MSVC don't have snprintf, vsnprintf in their CRTs.
+	Remap to the deprecated unix compatibility versions.
+*/
+
+#endif /* #if !defined (__IMG_DEFS_H__) */
+/*****************************************************************************
+ End of file (IMG_DEFS.H)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/include4/img_types.h b/drivers/gpu/pvr/include4/img_types.h
new file mode 100644
index 0000000..6d2761c
--- /dev/null
+++ b/drivers/gpu/pvr/include4/img_types.h
@@ -0,0 +1,231 @@
+/*************************************************************************/ /*!
+@Title          Global types for use by IMG APIs
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Defines type aliases for use by IMG APIs.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+#if   defined(LINUX) && defined(__KERNEL__)
+	#include "kernel_types.h"
+#elif defined(LINUX) || defined(__QNXNTO__) || defined(__METAG)
+	#include <stddef.h>			/* NULL */
+	#include <stdint.h>			/* intX_t/uintX_t, format specifiers */
+	#include <limits.h>			/* INT_MIN, etc */
+#else
+	#error C99 support not set up for this build
+#endif
+
+/* define all address space bit depths: */
+/* CPU virtual address space defaults to 32bits */
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS		32
+#endif
+
+/* Physical address space defaults to 32bits */
+#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
+#define IMG_ADDRSPACE_PHYSADDR_BITS		32
+#endif
+
+typedef unsigned int	IMG_UINT,	*IMG_PUINT;
+typedef signed int	IMG_INT,	*IMG_PINT;
+
+typedef uint8_t		IMG_UINT8,	*IMG_PUINT8;
+typedef uint8_t		IMG_BYTE,	*IMG_PBYTE;
+typedef int8_t		IMG_INT8,	*IMG_PINT8;
+typedef char		IMG_CHAR,	*IMG_PCHAR;
+
+typedef uint16_t	IMG_UINT16,	*IMG_PUINT16;
+typedef int16_t		IMG_INT16,	*IMG_PINT16;
+typedef uint32_t	IMG_UINT32,	*IMG_PUINT32;
+typedef int32_t		IMG_INT32,	*IMG_PINT32;
+
+#define IMG_UINT32_MAX  UINT32_MAX
+
+typedef uint64_t	IMG_UINT64, *IMG_PUINT64;
+typedef int64_t		IMG_INT64,  *IMG_PINT64;
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+/* Linux kernel mode does not use floating point */
+typedef float		IMG_FLOAT,	*IMG_PFLOAT;
+typedef double		IMG_DOUBLE, *IMG_PDOUBLE;
+#endif
+
+typedef	enum tag_img_bool
+{
+	IMG_FALSE		= 0,
+	IMG_TRUE		= 1,
+	IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+typedef void            IMG_VOID, *IMG_PVOID;
+
+typedef IMG_INT32       IMG_RESULT;
+
+#if defined(_WIN64)
+	typedef unsigned __int64	IMG_UINTPTR_T;
+	typedef signed   __int64    IMG_INTPTR_T;
+	typedef signed __int64		IMG_PTRDIFF_T;
+	typedef IMG_UINT64			IMG_SIZE_T;
+#else
+#if defined (__x86_64__) || !defined(USE_64BIT_COMPAT) || defined (__KERNEL__)
+	typedef size_t		IMG_SIZE_T;
+#else
+	typedef IMG_UINT64		IMG_SIZE_T;
+#endif
+	typedef uintptr_t   	IMG_UINTPTR_T;
+#endif
+
+#if defined(LINUX) && defined (__KERNEL__)
+	typedef IMG_PVOID       IMG_HANDLE;
+#elif defined(LINUX)
+	#if defined(USE_64BIT_COMPAT)
+		typedef IMG_UINT64	IMG_HANDLE;
+	#else
+		typedef IMG_UINT32	IMG_HANDLE;
+	#endif
+#else
+typedef void           *IMG_HANDLE;
+#endif
+
+typedef void**          IMG_HVOID,	* IMG_PHVOID;
+
+#define IMG_NULL        0 
+
+/* services/stream ID */
+typedef IMG_UINTPTR_T	IMG_SID;
+
+typedef IMG_UINTPTR_T	IMG_EVENTSID;
+
+/*
+ * Address types.
+ * All types used to refer to a block of memory are wrapped in structures
+ * to enforce some degree of type safety, i.e. a IMG_DEV_VIRTADDR cannot
+ * be assigned to a variable of type IMG_DEV_PHYADDR because they are not the
+ * same thing.
+ *
+ * There is an assumption that the system contains at most one non-cpu mmu,
+ * and a memory block is only mapped by the MMU once.
+ *
+ * Different devices could have offset views of the physical address space.
+ * 
+ */
+
+
+/*
+ *
+ * +------------+    +------------+      +------------+        +------------+
+ * |    CPU     |    |    DEV     |      |    DEV     |        |    DEV     |
+ * +------------+    +------------+      +------------+        +------------+
+ *       |                 |                   |                     |
+ *       | PVOID           |IMG_DEV_VIRTADDR   |IMG_DEV_VIRTADDR     |
+ *       |                 \-------------------/                     |
+ *       |                          |                                |
+ * +------------+             +------------+                         |     
+ * |    MMU     |             |    MMU     |                         |
+ * +------------+             +------------+                         | 
+ *       |                          |                                | 
+ *       |                          |                                |
+ *       |                          |                                |
+ *   +--------+                +---------+                      +--------+
+ *   | Offset |                | (Offset)|                      | Offset |
+ *   +--------+                +---------+                      +--------+    
+ *       |                          |                IMG_DEV_PHYADDR | 
+ *       |                          |                                |
+ *       |                          | IMG_DEV_PHYADDR                |
+ * +---------------------------------------------------------------------+ 
+ * |                         System Address bus                          |
+ * +---------------------------------------------------------------------+
+ *
+ */
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+/* device virtual address */
+typedef struct _IMG_DEV_VIRTADDR
+{
+	/* device virtual addresses are 32bit for now */
+	IMG_UINT32  uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var)		(IMG_UINT32)(var)
+	
+} IMG_DEV_VIRTADDR;
+
+typedef IMG_UINT32 IMG_DEVMEM_SIZE_T;
+
+/* cpu physical address */
+typedef struct _IMG_CPU_PHYADDR
+{
+	/* variable sized type (32,64) */
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+	/* variable sized type (32,64) */
+	IMG_UINT32 uiAddr;
+#else
+	IMG_UINT64 uiAddr;
+#endif
+} IMG_CPU_PHYADDR;
+
+/* device physical address */
+typedef struct _IMG_DEV_PHYADDR
+{
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+	/* variable sized type (32,64) */
+	IMG_UINT32 uiAddr;
+#else
+	IMG_UINT64 uiAddr;
+#endif
+} IMG_DEV_PHYADDR;
+
+/* system physical address */
+typedef struct _IMG_SYS_PHYADDR
+{
+	/* variable sized type (32,64) */
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+	/* variable sized type (32,64) */
+	IMG_UINT32 uiAddr;
+#else
+	IMG_UINT64 uiAddr;
+#endif
+} IMG_SYS_PHYADDR;
+
+#include "img_defs.h"
+
+#endif	/* __IMG_TYPES_H__ */
+/******************************************************************************
+ End of file (img_types.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/include4/kernel_types.h b/drivers/gpu/pvr/include4/kernel_types.h
new file mode 100644
index 0000000..b53da19
--- /dev/null
+++ b/drivers/gpu/pvr/include4/kernel_types.h
@@ -0,0 +1,136 @@
+/*************************************************************************/ /*!
+@Title          C99-compatible types and definitions for Linux kernel code
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/kernel.h>
+
+/* Limits of specified-width integer types */
+
+/* S8_MIN, etc were added in kernel version 3.14. The other versions are for
+ * earlier kernels. They can be removed once older kernels don't need to be
+ * supported.
+ */
+#ifdef S8_MIN
+	#define INT8_MIN	S8_MIN
+#else
+	#define INT8_MIN	(-128)
+#endif
+
+#ifdef S8_MAX
+	#define INT8_MAX	S8_MAX
+#else
+	#define INT8_MAX	127
+#endif
+
+#ifdef U8_MAX
+	#define UINT8_MAX	U8_MAX
+#else
+	#define UINT8_MAX	0xFF
+#endif
+
+#ifdef S16_MIN
+	#define INT16_MIN	S16_MIN
+#else
+	#define INT16_MIN	(-32768)
+#endif
+
+#ifdef S16_MAX
+	#define INT16_MAX	S16_MAX
+#else
+	#define INT16_MAX	32767
+#endif
+
+#ifdef U16_MAX
+	#define UINT16_MAX	U16_MAX
+#else
+	#define UINT16_MAX	0xFFFF
+#endif
+
+#ifdef S32_MIN
+	#define INT32_MIN	S32_MIN
+#else
+	#define INT32_MIN	(-2147483647 - 1)
+#endif
+
+#ifdef S32_MAX
+	#define INT32_MAX	S32_MAX
+#else
+	#define INT32_MAX	2147483647
+#endif
+
+#ifdef U32_MAX
+	#define UINT32_MAX	U32_MAX
+#else
+	#define UINT32_MAX	0xFFFFFFFF
+#endif
+
+#ifdef S64_MIN
+	#define INT64_MIN	S64_MIN
+#else
+	#define INT64_MIN	(-9223372036854775807LL)
+#endif
+
+#ifdef S64_MAX
+	#define INT64_MAX	S64_MAX
+#else
+	#define INT64_MAX	9223372036854775807LL
+#endif
+
+#ifdef U64_MAX
+	#define UINT64_MAX	U64_MAX
+#else
+	#define UINT64_MAX	0xFFFFFFFFFFFFFFFFULL
+#endif
+
+/* Macros for integer constants */
+#define INT8_C			S8_C
+#define UINT8_C			U8_C
+#define INT16_C			S16_C
+#define UINT16_C		U16_C
+#define INT32_C			S32_C
+#define UINT32_C		U32_C
+#define INT64_C			S64_C
+#define UINT64_C		U64_C
+
+/* Format conversion of integer types <inttypes.h> */
+/* Only define PRIX64 for the moment, as this is the only format macro that
+ * img_types.h needs.
+ */
+#define PRIX64		"llX"
diff --git a/drivers/gpu/pvr/include4/pdumpdefs.h b/drivers/gpu/pvr/include4/pdumpdefs.h
new file mode 100644
index 0000000..2ba36c3
--- /dev/null
+++ b/drivers/gpu/pvr/include4/pdumpdefs.h
@@ -0,0 +1,127 @@
+/*************************************************************************/ /*!
+@Title          PDUMP definitions header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    PDUMP definitions header
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if !defined (__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+typedef enum _PDUMP_PIXEL_FORMAT_
+{
+	PVRSRV_PDUMP_PIXEL_FORMAT_UNSUPPORTED = 0,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+	PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+	PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+	PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+	PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+	PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+	PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+	PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+	PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+	PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+	PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+	PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+	PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+	PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+	PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+	PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+	PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+	PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+	PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+	PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+	PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+	PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+	PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGBA8888 = 39,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ABGR4444 = 40,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGBA4444 = 41,
+	PVRSRV_PDUMP_PIXEL_FORMAT_BGRA4444 = 42,
+	PVRSRV_PDUMP_PIXEL_FORMAT_ABGR1555 = 43,
+	PVRSRV_PDUMP_PIXEL_FORMAT_RGBA5551 = 44,
+	PVRSRV_PDUMP_PIXEL_FORMAT_BGRA5551 = 45,
+	PVRSRV_PDUMP_PIXEL_FORMAT_BGR565 = 46,
+	PVRSRV_PDUMP_PIXEL_FORMAT_A8 = 47,
+	
+	PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PDUMP_PIXEL_FORMAT;
+
+typedef enum _PDUMP_MEM_FORMAT_
+{
+	PVRSRV_PDUMP_MEM_FORMAT_STRIDE = 0,
+	PVRSRV_PDUMP_MEM_FORMAT_RESERVED = 1,
+	PVRSRV_PDUMP_MEM_FORMAT_TILED = 8,
+	PVRSRV_PDUMP_MEM_FORMAT_TWIDDLED = 9,
+	PVRSRV_PDUMP_MEM_FORMAT_HYBRID = 10,
+	
+	PVRSRV_PDUMP_MEM_FORMAT_FORCE_I32 = 0x7fffffff
+} PDUMP_MEM_FORMAT;
+
+typedef enum _PDUMP_POLL_OPERATOR
+{
+	PDUMP_POLL_OPERATOR_EQUAL = 0,
+	PDUMP_POLL_OPERATOR_LESS = 1,
+	PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+	PDUMP_POLL_OPERATOR_GREATER = 3,
+	PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+	PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+	PDUMP_POLL_OPERATOR_FORCE_I32 = 0x7fffffff
+} PDUMP_POLL_OPERATOR;
+
+
+#endif /* __PDUMPDEFS_H__ */
+
+/*****************************************************************************
+ End of file (pdumpdefs.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/include4/pvr_debug.h b/drivers/gpu/pvr/include4/pvr_debug.h
new file mode 100644
index 0000000..be78c77
--- /dev/null
+++ b/drivers/gpu/pvr/include4/pvr_debug.h
@@ -0,0 +1,283 @@
+/*************************************************************************/ /*!
+@Title          PVR Debug Declarations
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provides debug functionality
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+
+#include "img_types.h"
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN	(512)
+
+/* These are privately used by pvr_debug, use the PVR_DBG_ defines instead */
+#define DBGPRIV_FATAL			0x001UL
+#define DBGPRIV_ERROR			0x002UL
+#define DBGPRIV_BUFFERED		0x004UL
+#define DBGPRIV_WARNING			0x008UL
+#define DBGPRIV_MESSAGE			0x010UL
+#define DBGPRIV_VERBOSE			0x020UL
+#define DBGPRIV_CALLTRACE		0x040UL
+#define DBGPRIV_ALLOC			0x080UL
+#define DBGPRIV_DBGDRV_MESSAGE	0x100UL
+
+#define DBGPRIV_DBGLEVEL_COUNT	9
+
+#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
+#define PVRSRV_NEED_PVR_ASSERT
+#endif
+
+#if defined(PVRSRV_NEED_PVR_ASSERT) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+#endif
+
+#if !defined(PVRSRV_NEED_PVR_TRACE) && (defined(DEBUG) || defined(TIMING))
+#define PVRSRV_NEED_PVR_TRACE
+#endif
+
+/* PVR_ASSERT() and PVR_DBG_BREAK handling */
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+#if defined(LINUX) && defined(__KERNEL__)
+/* In Linux kernel mode, use BUG() directly. This produces the correct
+   filename and line number in the panic message. */
+#define PVR_ASSERT(EXPR) do											\
+	{																\
+		if (!(EXPR))												\
+		{															\
+			PVRSRVDebugPrintf(DBGPRIV_FATAL, __FILE__, __LINE__,	\
+							  "Debug assertion failed!");			\
+			BUG();													\
+		}															\
+	} while (0)
+
+#else /* defined(LINUX) && defined(__KERNEL__) */
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+													   IMG_UINT32 ui32Line);
+
+#if defined(LINUX)
+	#define PVR_ASSERT(EXPR) do								\
+		{													\
+			if (!(EXPR))									\
+				PVRSRVDebugAssertFail(__FILE__, __LINE__);	\
+		} while (0)
+#else
+    #if defined (__QNXNTO__)
+	    #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+    #else
+	    #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__)
+    #endif
+#endif
+
+#endif /* defined(LINUX) && defined(__KERNEL__) */
+
+
+			#if defined(LINUX) && defined(__KERNEL__)
+				#define PVR_DBG_BREAK BUG()
+			#else
+				#define PVR_DBG_BREAK PVRSRVDebugAssertFail(__FILE__, __LINE__)
+			#endif
+
+#else  /* defined(PVRSRV_NEED_PVR_ASSERT) */
+
+	#define PVR_ASSERT(EXPR)
+	#define PVR_DBG_BREAK
+
+#endif /* defined(PVRSRV_NEED_PVR_ASSERT) */
+
+
+/* PVR_DPF() handling */
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#if defined(PVRSRV_NEW_PVR_DPF)
+
+	/* New logging mechanism */
+	#define PVR_DBG_FATAL		DBGPRIV_FATAL
+	#define PVR_DBG_ERROR		DBGPRIV_ERROR
+	#define PVR_DBG_BUFFERED	DBGPRIV_BUFFERED
+	#define PVR_DBG_WARNING		DBGPRIV_WARNING
+	#define PVR_DBG_MESSAGE		DBGPRIV_MESSAGE
+	#define PVR_DBG_VERBOSE		DBGPRIV_VERBOSE
+	#define PVR_DBG_CALLTRACE	DBGPRIV_CALLTRACE
+	#define PVR_DBG_ALLOC		DBGPRIV_ALLOC
+	#define PVR_DBGDRIV_MESSAGE	DBGPRIV_DBGDRV_MESSAGE
+
+	/* These levels are always on with PVRSRV_NEED_PVR_DPF */
+	#define __PVR_DPF_0x001UL(x...) PVRSRVDebugPrintf(DBGPRIV_FATAL, x)
+	#define __PVR_DPF_0x002UL(x...) PVRSRVDebugPrintf(DBGPRIV_ERROR, x)
+	#define __PVR_DPF_0x004UL(x...) PVRSRVDebugPrintf(DBGPRIV_BUFFERED, x)
+
+	/* Some are compiled out completely in release builds */
+#if defined(DEBUG)
+	#define __PVR_DPF_0x008UL(x...) PVRSRVDebugPrintf(DBGPRIV_WARNING, x)
+	#define __PVR_DPF_0x010UL(x...) PVRSRVDebugPrintf(DBGPRIV_MESSAGE, x)
+	#define __PVR_DPF_0x020UL(x...) PVRSRVDebugPrintf(DBGPRIV_VERBOSE, x)
+	#define __PVR_DPF_0x040UL(x...) PVRSRVDebugPrintf(DBGPRIV_CALLTRACE, x)
+	#define __PVR_DPF_0x080UL(x...) PVRSRVDebugPrintf(DBGPRIV_ALLOC, x)
+	#define __PVR_DPF_0x100UL(x...) PVRSRVDebugPrintf(DBGPRIV_DBGDRV_MESSAGE, x)
+
+#elif defined(PVR_DBGPRIV_LEVEL)
+
+#if (PVR_DBGPRIV_LEVEL >= DBGPRIV_WARNING)
+	#define __PVR_DPF_0x008UL(x...) PVRSRVDebugPrintf(DBGPRIV_WARNING, x)
+#else
+	#define __PVR_DPF_0x008UL(x...)
+#endif
+
+#if (PVR_DBGPRIV_LEVEL >= DBGPRIV_MESSAGE)
+	#define __PVR_DPF_0x010UL(x...) PVRSRVDebugPrintf(DBGPRIV_MESSAGE, x)
+#else
+	#define __PVR_DPF_0x010UL(x...)
+#endif
+
+#if (PVR_DBGPRIV_LEVEL >= DBGPRIV_VERBOSE)
+	#define __PVR_DPF_0x020UL(x...) PVRSRVDebugPrintf(DBGPRIV_VERBOSE, x)
+#else
+	#define __PVR_DPF_0x020UL(x...)
+#endif
+
+#if (PVR_DBGPRIV_LEVEL >= DBGPRIV_CALLTRACE)
+	#define __PVR_DPF_0x040UL(x...) PVRSRVDebugPrintf(DBGPRIV_CALLTRACE, x)
+#else
+	#define __PVR_DPF_0x040UL(x...)
+#endif
+
+#if (PVR_DBGPRIV_LEVEL >= DBGPRIV_ALLOC)
+	#define __PVR_DPF_0x080UL(x...) PVRSRVDebugPrintf(DBGPRIV_ALLOC, x)
+#else
+	#define __PVR_DPF_0x080UL(x...)
+#endif
+
+#if (PVR_DBGPRIV_LEVEL >= DBGPRIV_DBGDRV_MESSAGE)
+	#define __PVR_DPF_0x100UL(x...) PVRSRVDebugPrintf(DBGPRIV_DBGDRV_MESSAGE, x)
+#else
+	#define __PVR_DPF_0x100UL(x...)
+#endif
+
+#else
+	#define __PVR_DPF_0x008UL(x...)
+	#define __PVR_DPF_0x010UL(x...)
+	#define __PVR_DPF_0x020UL(x...)
+	#define __PVR_DPF_0x040UL(x...)
+	#define __PVR_DPF_0x080UL(x...)
+	#define __PVR_DPF_0x100UL(x...)
+#endif
+
+	/* Translate the different log levels to separate macros
+	 * so they can each be compiled out.
+	 */
+#if defined(DEBUG)
+	#define __PVR_DPF(lvl, x...) __PVR_DPF_ ## lvl (__FILE__, __LINE__, x)
+#else
+	#define __PVR_DPF(lvl, x...) __PVR_DPF_ ## lvl ("", 0, x)
+#endif
+
+	/* Get rid of the double bracketing */
+	#define PVR_DPF(x) __PVR_DPF x
+
+#else /* defined(PVRSRV_NEW_PVR_DPF) */
+
+	/* Old logging mechanism */
+	#define PVR_DBG_FATAL		DBGPRIV_FATAL,__FILE__, __LINE__
+	#define PVR_DBG_ERROR		DBGPRIV_ERROR,__FILE__, __LINE__
+	#define PVR_DBG_WARNING		DBGPRIV_WARNING,__FILE__, __LINE__
+	#define PVR_DBG_MESSAGE		DBGPRIV_MESSAGE,__FILE__, __LINE__
+	#define PVR_DBG_VERBOSE		DBGPRIV_VERBOSE,__FILE__, __LINE__
+	#define PVR_DBG_CALLTRACE	DBGPRIV_CALLTRACE,__FILE__, __LINE__
+	#define PVR_DBG_ALLOC		DBGPRIV_ALLOC,__FILE__, __LINE__
+	#define PVR_DBG_BUFFERED	DBGPRIV_BUFFERED,__FILE__, __LINE__
+	#define PVR_DBGDRIV_MESSAGE	DBGPRIV_DBGDRV_MESSAGE, "", 0
+
+	#define PVR_DPF(X)			PVRSRVDebugPrintf X
+
+#endif /* defined(PVRSRV_NEW_PVR_DPF) */
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+												   const IMG_CHAR *pszFileName,
+												   IMG_UINT32 ui32Line,
+												   const IMG_CHAR *pszFormat,
+												   ...) IMG_FORMAT_PRINTF(4, 5);
+
+#if defined(PVR_DBGPRIV_LEVEL) && defined(SUPPORT_ANDROID_PLATFORM)
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintfSetLevel(IMG_UINT32 ui32DebugLevel);
+#endif
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
+
+#else  /* defined(PVRSRV_NEED_PVR_DPF) */
+
+	#define PVR_DPF(X)
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+/* PVR_TRACE() handling */
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+	#define PVR_TRACE(X)	PVRSRVTrace X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
+	IMG_FORMAT_PRINTF(1, 2);
+
+#else /* defined(PVRSRV_NEED_PVR_TRACE) */
+
+	#define PVR_TRACE(X)
+
+#endif /* defined(PVRSRV_NEED_PVR_TRACE) */
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif	/* __PVR_DEBUG_H__ */
+
+/******************************************************************************
+ End of file (pvr_debug.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/pvr/include4/pvr_sync_user.h b/drivers/gpu/pvr/include4/pvr_sync_user.h
new file mode 100644
index 0000000..a44293f
--- /dev/null
+++ b/drivers/gpu/pvr/include4/pvr_sync_user.h
@@ -0,0 +1,137 @@
+/*************************************************************************/ /*!
+@File           pvr_sync_user.h
+@Title          Userspace definitions to use the kernel sync driver
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Version numbers and strings for PVR Consumer services
+				components.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _PVR_SYNC_USER_H_
+#define _PVR_SYNC_USER_H_
+
+#include <linux/ioctl.h>
+
+#ifdef __KERNEL__
+#include "sgxapi_km.h"
+#else
+#include "sgxapi.h"
+#endif
+
+#include "servicesext.h" // PVRSRV_SYNC_DATA
+#include "img_types.h"
+
+/* This matches the sw_sync create ioctl data */
+struct PVR_SYNC_CREATE_IOCTL_DATA
+{
+	/* Input: Name of this sync pt. Passed to base sync driver. */
+	char	name[32];
+
+	/* Input: An fd from a previous call to ALLOC ioctl. Cannot be <0. */
+	__s32	allocdSyncInfo;
+
+	/* Output: An fd returned from the CREATE ioctl. */
+	__s32	fence;
+};
+
+struct PVR_SYNC_ALLOC_IOCTL_DATA
+{
+	/* Output: An fd returned from the ALLOC ioctl */
+	__s32 fence;
+
+	/* Output: IMG_TRUE if the timeline looked idle at alloc time */
+	__u32 bTimelineIdle;
+};
+
+#define PVR_SYNC_DEBUG_MAX_POINTS 3
+
+typedef struct
+{
+	/* Output: A globally unique stamp/ID for the sync */
+	IMG_UINT64 ui64Stamp;
+
+	/* Output: The WOP snapshot for the sync */
+	IMG_UINT32 ui32WriteOpsPendingSnapshot;
+}
+PVR_SYNC_DEBUG;
+
+struct PVR_SYNC_DEBUG_IOCTL_DATA
+{
+	/* Input: Fence to acquire debug for */
+	int						iFenceFD;
+
+	/* Output: Number of points merged into this fence */
+	IMG_UINT32				ui32NumPoints;
+
+	struct
+	{
+		/* Output: Metadata for sync point */
+		PVR_SYNC_DEBUG		sMetaData;
+
+		/* Output: 'Live' sync information. */
+		PVRSRV_SYNC_DATA	sSyncData;
+	}
+	sSync[PVR_SYNC_DEBUG_MAX_POINTS];
+};
+
+struct PVR_SYNC_RENAME_IOCTL_DATA
+{
+	/* Input: Name of timeline. */
+	IMG_CHAR	szName[32];
+};
+
+#define PVR_SYNC_IOC_MAGIC	'W'
+
+#define PVR_SYNC_IOC_CREATE_FENCE \
+	_IOWR(PVR_SYNC_IOC_MAGIC, 0, struct PVR_SYNC_CREATE_IOCTL_DATA)
+
+#define PVR_SYNC_IOC_DEBUG_FENCE \
+	_IOWR(PVR_SYNC_IOC_MAGIC, 1, struct PVR_SYNC_DEBUG_IOCTL_DATA)
+
+#define PVR_SYNC_IOC_ALLOC_FENCE \
+	_IOWR(PVR_SYNC_IOC_MAGIC, 2, struct PVR_SYNC_ALLOC_IOCTL_DATA)
+
+#define PVR_SYNC_IOC_RENAME \
+	_IOWR(PVR_SYNC_IOC_MAGIC, 3, struct PVR_SYNC_RENAME_IOCTL_DATA)
+
+#define PVR_SYNC_IOC_FORCE_SW_ONLY \
+	_IO(PVR_SYNC_IOC_MAGIC, 4)
+
+#define PVRSYNC_MODNAME "pvr_sync"
+
+#endif /* _PVR_SYNC_USER_H_ */
diff --git a/drivers/gpu/pvr/include4/pvrmodule.h b/drivers/gpu/pvr/include4/pvrmodule.h
new file mode 100644
index 0000000..267c7b6
--- /dev/null
+++ b/drivers/gpu/pvr/include4/pvrmodule.h
@@ -0,0 +1,48 @@
+/*************************************************************************/ /*!
+@Title          Module Author and License.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef	_PVRMODULE_H_
+#define	_PVRMODULE_H_
+
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("Dual MIT/GPL");
+
+#endif	/* _PVRMODULE_H_ */
diff --git a/drivers/gpu/pvr/include4/pvrversion.h b/drivers/gpu/pvr/include4/pvrversion.h
new file mode 100644
index 0000000..b2457fe
--- /dev/null
+++ b/drivers/gpu/pvr/include4/pvrversion.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@File
+@Title          Version numbers and strings.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Version numbers and strings for PVR Consumer services
+                components.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVR_STR(X) #X
+#define PVR_STR2(X) PVR_STR(X)
+
+#define PVRVERSION_MAJ               1
+#define PVRVERSION_MIN               17
+
+#define PVRVERSION_FAMILY           "sgxddk"
+#define PVRVERSION_BRANCHNAME       "1.17"
+#define PVRVERSION_BUILD             4948957
+#define PVRVERSION_BSCONTROL        "SGX_DDK_Android"
+
+#define PVRVERSION_STRING           "SGX_DDK_Android sgxddk 1.17@" PVR_STR2(PVRVERSION_BUILD)
+#define PVRVERSION_STRING_SHORT     "1.17@" PVR_STR2(PVRVERSION_BUILD) ""
+
+#define COPYRIGHT_TXT               "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
+
+#define PVRVERSION_BUILD_HI          494
+#define PVRVERSION_BUILD_LO          8957
+#define PVRVERSION_STRING_NUMERIC    PVR_STR2(PVRVERSION_MAJ) "." PVR_STR2(PVRVERSION_MIN) "." PVR_STR2(PVRVERSION_BUILD_HI) "." PVR_STR2(PVRVERSION_BUILD_LO)
+
+#endif /* _PVRVERSION_H_ */
diff --git a/drivers/gpu/pvr/include4/services.h b/drivers/gpu/pvr/include4/services.h
new file mode 100644
index 0000000..7ee9318
--- /dev/null
+++ b/drivers/gpu/pvr/include4/services.h
@@ -0,0 +1,1641 @@
+/*************************************************************************/ /*!
+@Title          Services API Header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Exported services API details
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __SERVICES_H__
+#define __SERVICES_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "pdumpdefs.h"
+
+
+/* The comment below is the front page for code-generated doxygen documentation */
+/*!
+ ******************************************************************************
+ @mainpage
+ This document details the APIs and implementation of the Consumer Services.
+ It is intended to be used in conjunction with the Consumer Services
+ Software Architectural Specification and the Consumer Services Software
+ Functional Specification.
+ *****************************************************************************/
+
+/******************************************************************************
+ * 	#defines
+ *****************************************************************************/
+
+/* 4k page size definition */
+#define PVRSRV_4K_PAGE_SIZE		4096UL
+
+#define PVRSRV_MAX_CMD_SIZE		1024/*!< max size in bytes of a command */
+
+#define PVRSRV_MAX_DEVICES		16	/*!< Largest supported number of devices on the system */
+
+#define EVENTOBJNAME_MAXLENGTH (64)
+
+/*
+	Flags associated with memory allocation
+	(bits 0-11)
+*/
+#define PVRSRV_MEM_READ						(1U<<0)
+#define PVRSRV_MEM_WRITE					(1U<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT			(1U<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ				(1U<<3)
+#define PVRSRV_MEM_INTERLEAVED				(1U<<4)
+#define PVRSRV_MEM_DUMMY					(1U<<5)
+#define PVRSRV_MEM_EDM_PROTECT				(1U<<6)
+#define PVRSRV_MEM_ZERO						(1U<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR	(1U<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION	(1U<<9)
+#define PVRSRV_MEM_NO_RESMAN				(1U<<10)
+#define PVRSRV_MEM_EXPORTED					(1U<<11)
+
+/*
+	Heap Attribute flags
+	(bits 12-23)
+*/
+#define PVRSRV_HAP_CACHED					(1U<<12)
+#define PVRSRV_HAP_UNCACHED					(1U<<13)
+#define PVRSRV_HAP_WRITECOMBINE				(1U<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK			(PVRSRV_HAP_CACHED|PVRSRV_HAP_UNCACHED|PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY				(1U<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS			(1U<<16)
+#define PVRSRV_HAP_MULTI_PROCESS			(1U<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS	(1U<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL			(1U<<19)
+#define PVRSRV_HAP_MAPTYPE_MASK				(PVRSRV_HAP_KERNEL_ONLY \
+                                            |PVRSRV_HAP_SINGLE_PROCESS \
+                                            |PVRSRV_HAP_MULTI_PROCESS \
+                                            |PVRSRV_HAP_FROM_EXISTING_PROCESS \
+                                            |PVRSRV_HAP_NO_CPU_VIRTUAL)
+
+/*
+	Allows user allocations to override heap attributes
+	(Bits shared with heap flags)
+*/
+#define PVRSRV_MEM_CACHED					PVRSRV_HAP_CACHED
+#define PVRSRV_MEM_UNCACHED					PVRSRV_HAP_UNCACHED
+#define PVRSRV_MEM_WRITECOMBINE				PVRSRV_HAP_WRITECOMBINE
+
+/*
+	Backing store flags (defined internally)
+	(bits 24-26)
+*/
+#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT	(24)
+
+/*
+	Per allocation/mapping flags
+	(bits 27-30)
+ */
+#define PVRSRV_MAP_NOUSERVIRTUAL            (1UL<<27)
+#define PVRSRV_MEM_XPROC  					(1U<<28)
+/* Bit 29 is unused */
+#define PVRSRV_MEM_ALLOCATENONCACHEDMEM		(1UL<<30)
+
+/*
+	Internal allocation/mapping flags
+	(bit 31)
+*/
+#define PVRSRV_MEM_SPARSE					(1U<<31)
+
+
+/*
+ * How much context we lose on a (power) mode change
+ */
+#define PVRSRV_NO_CONTEXT_LOSS					0		/*!< Do not lose state on power down */
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT			1		/*!< lose state on power down */
+#define PVRSRV_PRE_STATE_CHANGE_MASK			0x80	/*!< power state change mask */
+
+
+/*
+ * Device cookie defines
+ */
+#define PVRSRV_DEFAULT_DEV_COOKIE			(1)	 /*!< default device cookie */
+
+
+/*
+ * Misc Info. present flags
+ */
+#define PVRSRV_MISC_INFO_TIMER_PRESENT					(1U<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT				(1U<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT				(1U<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT		(1U<<3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT				(1U<<4)
+#define PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT				(1U<<5)
+#define PVRSRV_MISC_INFO_FREEMEM_PRESENT				(1U<<6)
+#define PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT			(1U<<7)
+#define PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT			(1U<<8)
+#define PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT	(1U<<9)
+
+#define PVRSRV_MISC_INFO_RESET_PRESENT					(1U<<31)
+
+/* PDUMP defines */
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE			20
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE			200
+
+
+/*
+	Flags for PVRSRVChangeDeviceMemoryAttributes call.
+*/
+#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT		0x00000001
+
+/*
+	Flags for PVRSRVMapExtMemory and PVRSRVUnmapExtMemory
+	ALTERNATEVA		-	Used when mapping multiple virtual addresses to the same physical address. Set this flag on extra maps.
+	PHYSCONTIG		-	Physical pages are contiguous (unused)
+*/
+#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA			0x00000001
+#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG			0x00000002
+
+/*
+	Flags for PVRSRVModifySyncOps
+	WO_INC		-	Used to increment "WriteOpsPending/complete of sync info"
+	RO_INC		-	Used to increment "ReadOpsPending/complete of sync info"
+	RO2_INC		-	Used to increment "ReadOps2Pending/complete of sync info"
+*/
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC				(1U<<0)
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC				(1U<<1)
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO2_INC				(1U<<2)
+
+/*
+	Flags for Services connection.
+	Allows to define per-client policy for Services
+*/
+#define SRV_FLAGS_PERSIST		0x1
+#define SRV_FLAGS_PDUMP_ACTIVE	0x2
+
+/*
+	Pdump flags which are accessible to Services clients
+*/
+#define PVRSRV_PDUMP_FLAGS_CONTINUOUS		0x1
+
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+
+/*!
+ ******************************************************************************
+ * List of known device types.
+ *****************************************************************************/
+typedef enum _PVRSRV_DEVICE_TYPE_
+{
+	PVRSRV_DEVICE_TYPE_UNKNOWN			= 0 ,
+	PVRSRV_DEVICE_TYPE_MBX1				= 1 ,
+	PVRSRV_DEVICE_TYPE_MBX1_LITE		= 2 ,
+
+	PVRSRV_DEVICE_TYPE_M24VA			= 3,
+	PVRSRV_DEVICE_TYPE_MVDA2			= 4,
+	PVRSRV_DEVICE_TYPE_MVED1			= 5,
+	PVRSRV_DEVICE_TYPE_MSVDX			= 6,
+
+	PVRSRV_DEVICE_TYPE_SGX				= 7,
+
+	PVRSRV_DEVICE_TYPE_VGX				= 8,
+
+	/* 3rd party devices take ext type */
+	PVRSRV_DEVICE_TYPE_EXT				= 9,
+
+    PVRSRV_DEVICE_TYPE_LAST             = 9,
+
+	PVRSRV_DEVICE_TYPE_FORCE_I32		= 0x7fffffff
+
+} PVRSRV_DEVICE_TYPE;
+
+#define HEAP_ID( _dev_ , _dev_heap_idx_ )	(  ((_dev_)<<24) | ((_dev_heap_idx_)&((1<<24)-1))  )
+#define HEAP_IDX( _heap_id_ )				( (_heap_id_)&((1<<24) - 1 ) )
+#define HEAP_DEV( _heap_id_ )				( (_heap_id_)>>24 )
+
+/* common undefined heap ID define */
+#define PVRSRV_UNDEFINED_HEAP_ID			(~0LU)
+
+/*!
+ ******************************************************************************
+ * User Module type
+ *****************************************************************************/
+typedef enum
+{
+	IMG_EGL				= 0x00000001,
+	IMG_OPENGLES1		= 0x00000002,
+	IMG_OPENGLES2		= 0x00000003,
+	IMG_D3DM			= 0x00000004,
+	IMG_SRV_UM			= 0x00000005,
+	IMG_OPENVG			= 0x00000006,
+	IMG_SRVCLIENT		= 0x00000007,
+	IMG_VISTAKMD		= 0x00000008,
+	IMG_VISTA3DNODE		= 0x00000009,
+	IMG_VISTAMVIDEONODE	= 0x0000000A,
+	IMG_VISTAVPBNODE	= 0x0000000B,
+	IMG_OPENGL			= 0x0000000C,
+	IMG_D3D				= 0x0000000D,
+#if defined(SUPPORT_GRAPHICS_HAL) || defined(SUPPORT_COMPOSER_HAL)
+	IMG_ANDROID_HAL		= 0x0000000E,
+#endif
+#if defined(SUPPORT_OPENCL)
+	IMG_OPENCL			= 0x0000000F,
+#endif
+
+	IMG_MODULE_UNDEF	= 0xFFFFFFFF
+} IMG_MODULE_ID;
+
+
+#define APPHINT_MAX_STRING_SIZE	256
+
+/*!
+ ******************************************************************************
+ * IMG data types
+ *****************************************************************************/
+typedef enum
+{
+	IMG_STRING_TYPE		= 1,
+	IMG_FLOAT_TYPE		,
+	IMG_UINT_TYPE		,
+	IMG_INT_TYPE		,
+	IMG_FLAG_TYPE
+}IMG_DATA_TYPE;
+
+
+/******************************************************************************
+ * Structure definitions.
+ *****************************************************************************/
+
+/*!
+ * Forward declaration
+ */
+typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+
+/*!
+ ******************************************************************************
+ * Device identifier structure
+ *****************************************************************************/
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+	PVRSRV_DEVICE_TYPE		eDeviceType;		/*!< Identifies the type of the device */
+	PVRSRV_DEVICE_CLASS		eDeviceClass;		/*!< Identifies more general class of device - display/3d/mpeg etc */
+	IMG_UINT32			ui32DeviceIndex;	/*!< Index of the device within the system */
+#if defined(USE_64BIT_COMPAT)
+	IMG_UINT32			ui32Padding;
+#endif
+#if defined(PDUMP)
+	IMG_CHAR			*pszPDumpDevName;	/*!< Pdump memory bank name */
+	IMG_CHAR			*pszPDumpRegName;	/*!< Pdump register bank name */
+#endif
+
+} PVRSRV_DEVICE_IDENTIFIER;
+
+
+/******************************************************************************
+ * Client dev info
+ ******************************************************************************
+ */
+typedef struct _PVRSRV_CLIENT_DEV_DATA_
+{
+	IMG_UINT32		ui32NumDevices;				/*!< Number of services-managed devices connected */
+	PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES];		/*!< Device identifiers */
+	PVRSRV_ERROR	(*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);	/*< device-specific connection callback */
+	PVRSRV_ERROR	(*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);		/*!< device-specific debug trace callback */
+
+} PVRSRV_CLIENT_DEV_DATA;
+
+
+/*!
+ ******************************************************************************
+ * Kernel Services connection structure
+ *****************************************************************************/
+typedef struct _PVRSRV_CONNECTION_
+{
+	IMG_HANDLE hServices;					/*!< UM IOCTL handle */
+	IMG_UINT32 ui32ProcessID;				/*!< Process ID for resource locking */
+	PVRSRV_CLIENT_DEV_DATA	sClientDevData;	/*!< Client device data */
+	IMG_UINT32 ui32SrvFlags;				/*!< Per-client Services flags */
+}PVRSRV_CONNECTION;
+
+
+/*!
+ ******************************************************************************
+ * This structure allows the user mode glue code to have an OS independent
+ * set of prototypes.
+ *****************************************************************************/
+typedef struct _PVRSRV_DEV_DATA_
+{
+	IMG_HANDLE			hConnection;	/*!< Services connection info */
+	IMG_HANDLE			hDevCookie;	/*!< Dev cookie */
+
+} PVRSRV_DEV_DATA;
+
+/*!
+ ******************************************************************************
+ * address:value update structure
+ *****************************************************************************/
+typedef struct _PVRSRV_MEMUPDATE_
+{
+	IMG_UINT32			ui32UpdateAddr;		/*!< Address */
+	IMG_UINT32			ui32UpdateVal;		/*!< value */
+} PVRSRV_MEMUPDATE;
+
+/*!
+ ******************************************************************************
+ * address:value register structure
+ *****************************************************************************/
+typedef struct _PVRSRV_HWREG_
+{
+	IMG_UINT32			ui32RegAddr;	/*!< Address */
+	IMG_UINT32			ui32RegVal;		/*!< value */
+} PVRSRV_HWREG;
+
+/*!
+ ******************************************************************************
+ * Implementation details for memory handling
+ *****************************************************************************/
+typedef struct _PVRSRV_MEMBLK_
+{
+	IMG_DEV_VIRTADDR	sDevVirtAddr;			/*!< Address of the memory in the IMG MMUs address space */
+	IMG_HANDLE			hOSMemHandle;			/*!< Stores the underlying memory allocation handle */
+	IMG_HANDLE			hOSWrapMem;				/*!< FIXME: better way to solve this problem */
+	IMG_HANDLE			hBuffer;				/*!< Stores the BM_HANDLE for the underlying memory management */
+	IMG_HANDLE			hResItem;				/*!< handle to resource item for allocate */
+	IMG_SYS_PHYADDR	 	*psIntSysPAddr;
+
+} PVRSRV_MEMBLK;
+
+/*!
+ ******************************************************************************
+ * Memory Management (externel interface)
+ *****************************************************************************/
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+typedef struct _DEVMEM_UNMAPPING_TIME_STATS_
+{
+	IMG_UINT32	ui32TimeToCPUUnmap;
+	IMG_UINT32	ui32TimeToDevUnmap;
+} DEVMEM_UNMAPPING_TIME_STATS;
+
+typedef struct _PVRSRV_DEVMEM_TIMING_STATS_
+{
+	/* This struct holds time taken to map/unmap device memory into CPU/GPU in microsec granularity */
+	struct
+	{
+		IMG_UINT32	ui32TimeToCPUMap;
+		IMG_UINT32	ui32TimeToDevMap;
+	} sDevMemMapTimes;
+
+	DEVMEM_UNMAPPING_TIME_STATS *psDevMemUnmapTimes;	/* User supplied space for "unmap" timings */
+} PVRSRV_DEVMEM_TIMING_STATS;
+#endif
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO;
+
+typedef struct _PVRSRV_CLIENT_MEM_INFO_
+{
+	/* CPU Virtual Address */
+	IMG_PVOID				pvLinAddr;
+
+	/* CPU Virtual Address (for kernel mode) */
+	IMG_PVOID				pvLinAddrKM;
+
+	/* Device Virtual Address */
+	IMG_DEV_VIRTADDR		sDevVAddr;
+
+	/* allocation flags */
+	IMG_UINT32				ui32Flags;
+
+	/* client allocation flags */
+	IMG_UINT32				ui32ClientFlags;
+
+	/* allocation size in bytes */
+	IMG_SIZE_T				uAllocSize;
+
+
+	/* ptr to associated client sync info - NULL if no sync */
+	struct _PVRSRV_CLIENT_SYNC_INFO_	*psClientSyncInfo;
+
+	/* handle to client mapping data (OS specific) */
+	IMG_HANDLE							hMappingInfo;
+
+	/* handle to kernel mem info */
+	IMG_HANDLE							hKernelMemInfo;
+
+	/* resman handle for UM mapping clean-up */
+	IMG_HANDLE							hResItem;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+	#if !defined(USE_CODE)
+	/* Globally unique "stamp" for allocation (not re-used until wrap) */
+	IMG_UINT64							ui64Stamp;
+	#else /* !defined(USE_CODE) */
+	IMG_UINT32							dummy1;
+	IMG_UINT32							dummy2;
+	#endif /* !defined(USE_CODE) */
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
+#if defined(SUPPORT_ION)
+	IMG_SIZE_T							uiIonBufferSize;
+#endif /* defined(SUPPORT_ION) */
+#if defined(SUPPORT_DMABUF)
+	IMG_SIZE_T							uiDmaBufSize;
+#endif /* defined(SUPPORT_ION) */
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	PVRSRV_DEVMEM_TIMING_STATS			sDevMemTimingStats;
+#endif
+
+	/*
+		ptr to next mem info
+		D3D uses psNext for mid-scene texture reload.
+	*/
+	struct _PVRSRV_CLIENT_MEM_INFO_		*psNext;
+
+} PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+
+
+/*!
+ ******************************************************************************
+ * Memory Heap Information
+ *****************************************************************************/
+#define PVRSRV_MAX_CLIENT_HEAPS (32)
+typedef struct _PVRSRV_HEAP_INFO_
+{
+	IMG_UINT32			ui32HeapID;
+#if defined(USE_64BIT_COMPAT)
+	IMG_UINT32			ui32Padding;
+#endif
+	IMG_HANDLE 			hDevMemHeap;
+	IMG_DEV_VIRTADDR		sDevVAddrBase;
+	IMG_UINT32			ui32HeapByteSize;
+	IMG_UINT32			ui32Attribs;
+	IMG_UINT32			ui32XTileStride;
+}PVRSRV_HEAP_INFO;
+
+
+
+
+/*
+	Event Object information structure
+*/
+typedef struct _PVRSRV_EVENTOBJECT_
+{
+	/* globally unique name of the event object */
+	IMG_CHAR	szName[EVENTOBJNAME_MAXLENGTH];
+	/* kernel specific handle for the event object */
+	IMG_HANDLE	hOSEventKM;
+
+} PVRSRV_EVENTOBJECT;
+
+/*
+	Cache operation type
+*/
+typedef enum
+{
+	PVRSRV_MISC_INFO_CPUCACHEOP_NONE = 0,
+	PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN,
+	PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH,
+	PVRSRV_MISC_INFO_CPUCACHEOP_MAX = 0x7fffffff
+} PVRSRV_MISC_INFO_CPUCACHEOP_TYPE;
+
+/*!
+ ******************************************************************************
+ * Structure to retrieve misc. information from services
+ *****************************************************************************/
+typedef struct _PVRSRV_MISC_INFO_
+{
+	IMG_UINT32	ui32StateRequest;		/*!< requested State Flags */
+	IMG_UINT32	ui32StatePresent;		/*!< Present/Valid State Flags */
+
+	/*!< SOC Timer register */
+	IMG_VOID	*pvSOCTimerRegisterKM;
+	IMG_VOID	*pvSOCTimerRegisterUM;
+	IMG_HANDLE	hSOCTimerRegisterOSMemHandle;
+	IMG_HANDLE	hSOCTimerRegisterMappingInfo;
+
+	/*!< SOC Clock Gating registers */
+	IMG_VOID	*pvSOCClockGateRegs;
+	IMG_UINT32	ui32SOCClockGateRegsSize;
+
+	/* Memory Stats/DDK version string depending on ui32StateRequest flags */
+	IMG_CHAR	*pszMemoryStr;
+	IMG_UINT32	ui32MemoryStrLen;
+
+	/* global event object */
+	PVRSRV_EVENTOBJECT	sGlobalEventObject;//FIXME: should be private to services
+	IMG_HANDLE			hOSGlobalEvent;
+
+	/* Note: add misc. items as required */
+	IMG_UINT32	aui32DDKVersion[4];
+
+	/*!< CPU cache flush controls: */
+	struct
+	{
+		/*!< Defer the CPU cache op to the next HW op to be submitted (else flush now) */
+		IMG_BOOL bDeferOp;
+
+		/*!< Type of cache operation to perform */
+		PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
+
+		/* This union is a bit unsightly. We need it because we'll use the psMemInfo
+		 * directly in the srvclient PVRSRVGetMiscInfo code, and then convert it
+		 * to a kernel meminfo if required. Try to not waste space.
+		 */
+		union
+		{
+			/*!< Input client meminfo (UM side) */
+			PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
+
+			/*!< Output kernel meminfo (Bridge+KM side) */
+			IMG_HANDLE hKernelMemInfo;
+		} u;
+
+		/*!< Offset in MemInfo to start cache op */
+		IMG_VOID *pvBaseVAddr;
+
+		/*!< Length of range to perform cache op  */
+		IMG_UINT32	ui32Length;
+	} sCacheOpCtl;
+
+	/*!< Meminfo refcount controls: */
+	struct
+	{
+		/* This union is a bit unsightly. We need it because we'll use the psMemInfo
+		 * directly in the srvclient PVRSRVGetMiscInfo code, and then convert it
+		 * to a kernel meminfo if required. Try to not waste space.
+		 */
+		union
+		{
+			/*!< Input client meminfo (UM side) */
+			PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
+
+			/*!< Output kernel meminfo (Bridge+KM side) */
+			IMG_HANDLE hKernelMemInfo;
+		} u;
+
+		/*!< Resulting refcount */
+		IMG_UINT32 ui32RefCount;
+	} sGetRefCountCtl;
+
+	IMG_UINT32 ui32PageSize;
+} PVRSRV_MISC_INFO;
+
+/*!
+ ******************************************************************************
+ * Synchronisation token
+ *****************************************************************************/
+typedef struct _PVRSRV_SYNC_TOKEN_
+{
+	/* This token is supposed to be passed around as an opaque object
+	   - caller should not rely on the internal fields staying the same.
+	   The fields are hidden in sPrivate in order to reinforce this. */
+	struct
+	{
+		IMG_HANDLE hKernelSyncInfo;
+		IMG_UINT32 ui32ReadOpsPendingSnapshot;
+		IMG_UINT32 ui32WriteOpsPendingSnapshot;
+		IMG_UINT32 ui32ReadOps2PendingSnapshot;
+	} sPrivate;
+} PVRSRV_SYNC_TOKEN;
+
+
+/******************************************************************************
+ * PVR Client Event handling in Services
+ *****************************************************************************/
+typedef enum _PVRSRV_CLIENT_EVENT_
+{
+	PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0
+} PVRSRV_CLIENT_EVENT;
+
+typedef IMG_VOID (*PFN_QUEUE_COMMAND_COMPLETE)(IMG_HANDLE hCallbackData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(IMG_CONST PVRSRV_CLIENT_EVENT eEvent,
+											PVRSRV_DEV_DATA *psDevData,
+											IMG_PVOID pvData);
+
+/******************************************************************************
+ * PVR Services API prototypes.
+ *****************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION **ppsConnection, IMG_UINT32 ui32SrvFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(IMG_HANDLE hConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevices(IMG_CONST PVRSRV_CONNECTION 			*psConnection,
+													IMG_UINT32 					*puiNumDevices,
+													PVRSRV_DEVICE_IDENTIFIER 	*puiDevIDs);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceData(IMG_CONST PVRSRV_CONNECTION 	*psConnection,
+													IMG_UINT32			uiDevIndex,
+													PVRSRV_DEV_DATA		*psDevData,
+													PVRSRV_DEVICE_TYPE	eDeviceType);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfo (IMG_HANDLE hConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseMiscInfo (IMG_HANDLE hConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPollForValue ( const PVRSRV_CONNECTION *psConnection,
+							IMG_HANDLE hOSEvent,
+							volatile IMG_UINT32 *pui32LinMemAddr,
+							IMG_UINT32 ui32Value,
+							IMG_UINT32 ui32Mask,
+							IMG_UINT32 ui32Waitus,
+							IMG_UINT32 ui32Tries);
+
+/* memory APIs */
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE *phDevMemContext,
+											IMG_UINT32 *pui32SharedHeapCount,
+											PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE 			hDevMemContext
+	);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE hDevMemContext,
+											IMG_UINT32 *pui32SharedHeapCount,
+											PVRSRV_HEAP_INFO *psHeapInfo);
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+	#define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+		(PVR_TRACE(("PVRSRVAllocDeviceMem(" #psDevData "," #hDevMemHeap "," #ui32Attribs "," #ui32Size "," #ui32Alignment "," #ppsMemInfo ")" \
+			": " logStr " (size = 0x%lx)", (unsigned long)ui32Size)), \
+		PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo))
+#else
+	#define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+		PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem2(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+									IMG_HANDLE		hDevMemHeap,
+									IMG_UINT32		ui32Attribs,
+									IMG_SIZE_T		ui32Size,
+									IMG_SIZE_T		ui32Alignment,
+									IMG_PVOID		pvPrivData,
+									IMG_UINT32		ui32PrivDataLength,
+									PVRSRV_CLIENT_MEM_INFO	**ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+									IMG_HANDLE		hDevMemHeap,
+									IMG_UINT32		ui32Attribs,
+									IMG_SIZE_T		ui32Size,
+									IMG_SIZE_T		ui32Alignment,
+									PVRSRV_CLIENT_MEM_INFO	**ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMem(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+								PVRSRV_CLIENT_MEM_INFO		*psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+												PVRSRV_CLIENT_MEM_INFO		*psMemInfo,
+												IMG_HANDLE					*phMemInfo
+	);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_HANDLE			hDevMemHeap,
+											IMG_DEV_VIRTADDR	*psDevVAddr,
+											IMG_SIZE_T			ui32Size,
+											IMG_SIZE_T			ui32Alignment,
+											PVRSRV_CLIENT_MEM_INFO		**ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+													PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+									IMG_HANDLE hKernelMemInfo,
+									IMG_HANDLE hDstDevMemHeap,
+									PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapExtMemory (IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+									PVRSRV_CLIENT_MEM_INFO		*psMemInfo,
+									IMG_SYS_PHYADDR				*psSysPAddr,
+									IMG_UINT32					ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+									PVRSRV_CLIENT_MEM_INFO		*psMemInfo,
+									IMG_UINT32					ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+												IMG_HANDLE				hDevMemContext,
+												IMG_SIZE_T 				ui32ByteSize,
+												IMG_SIZE_T				ui32PageOffset,
+												IMG_BOOL				bPhysContig,
+												IMG_SYS_PHYADDR	 		*psSysPAddr,
+												IMG_VOID 				*pvLinAddr,
+												IMG_UINT32				ui32Flags,
+												PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+												PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+PVRSRV_ERROR PVRSRVChangeDeviceMemoryAttributes(IMG_CONST PVRSRV_DEV_DATA			*psDevData,
+												PVRSRV_CLIENT_MEM_INFO	*psClientMemInfo,
+												IMG_UINT32				ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+									  IMG_SYS_PHYADDR sSysPhysAddr,
+									  IMG_UINT32 uiSizeInBytes,
+									  IMG_PVOID *ppvUserAddr,
+									  IMG_UINT32 *puiActualSize,
+									  IMG_PVOID *ppvProcess);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										IMG_PVOID pvUserAddr,
+										IMG_PVOID pvProcess);
+
+#if defined(LINUX)
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem2(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+												 PVRSRV_CLIENT_MEM_INFO		*psMemInfo,
+												 IMG_INT					*iFd);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory2(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+												 IMG_INT					iFd,
+												 IMG_HANDLE					hDstDevMemHeap,
+												 PVRSRV_CLIENT_MEM_INFO		**ppsDstMemInfo);
+#endif /* defined(LINUX) */
+
+#if defined(SUPPORT_TEXTURE_ALLOC_NOMAP)
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData, PVRSRV_CLIENT_MEM_INFO *psMemInfo, void **ppvLinAddr);
+
+IMG_IMPORT
+void IMG_CALLCONV PVRSRVUnmapDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData, PVRSRV_CLIENT_MEM_INFO *psMemInfo, void **ppvLinAddr);
+#endif	/* defined(SUPPORT_TEXTURE_ALLOC_NOMAP) */
+
+#if defined(SUPPORT_ION)
+PVRSRV_ERROR PVRSRVMapIonHandle(const PVRSRV_DEV_DATA *psDevData,
+								IMG_HANDLE hDevMemHeap,
+								IMG_UINT32 ui32NumFDs,
+								IMG_INT    *paiBufferFDs,
+								IMG_UINT32 ui32ChunkCount,
+								IMG_SIZE_T *pauiOffset,
+								IMG_SIZE_T *pauiSize,
+								IMG_UINT32 ui32Attribs,
+								PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+PVRSRV_ERROR PVRSRVUnmapIonHandle(const PVRSRV_DEV_DATA *psDevData,
+								  PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+#endif /* defined (SUPPORT_ION) */
+
+#if defined(SUPPORT_DMABUF)
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVMapDmaBuf(const PVRSRV_DEV_DATA *psDevData,
+								const IMG_HANDLE hDevMemHeap,
+								const IMG_UINT32 ui32Attribs,
+								const IMG_INT iDmaBufFD,
+								const IMG_SIZE_T uiDmaBufOffset,
+								const IMG_SIZE_T uiDmaBufSize,
+								PVRSRV_CLIENT_MEM_INFO **ppsMemInfo,
+								IMG_SIZE_T *puiMemInfoOffset);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVMapFullDmaBuf(const PVRSRV_DEV_DATA *psDevData,
+								const IMG_HANDLE hDevMemHeap,
+								const IMG_UINT32 ui32Attribs,
+								const IMG_INT iDmaBufFD,
+								PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVUnmapDmaBuf(const PVRSRV_DEV_DATA *psDevData,
+								  PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+#endif /* SUPPORT_DMABUF */
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMemSparse(const PVRSRV_DEV_DATA *psDevData,
+													IMG_HANDLE hDevMemHeap,
+													IMG_UINT32 ui32Attribs,
+													IMG_SIZE_T uAlignment,
+													IMG_UINT32 ui32ChunkSize,
+													IMG_UINT32 ui32NumVirtChunks,
+													IMG_UINT32 ui32NumPhysChunks,
+													IMG_BOOL *pabMapChunk,
+													PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+/******************************************************************************
+ * PVR Allocation Synchronisation Functionality...
+ *****************************************************************************/
+
+typedef enum _PVRSRV_SYNCVAL_MODE_
+{
+	PVRSRV_SYNCVAL_READ				= IMG_TRUE,
+	PVRSRV_SYNCVAL_WRITE			= IMG_FALSE
+
+} PVRSRV_SYNCVAL_MODE, *PPVRSRV_SYNCVAL_MODE;
+
+typedef IMG_UINT32 PVRSRV_SYNCVAL;
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT PVRSRV_SYNCVAL PVRSRVGetPendingOpSyncVal(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+	PVRSRV_SYNCVAL_MODE eMode);
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										IMG_HANDLE hDevMemContext,
+										IMG_HANDLE hDeviceClassBuffer,
+										PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+/******************************************************************************
+ * Common Device Class Enumeration
+ *****************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDeviceClass(IMG_HANDLE hConnection,
+													PVRSRV_DEVICE_CLASS DeviceClass,
+													IMG_UINT32 *pui32DevCount,
+													IMG_UINT32 *pui32DevID);
+
+/******************************************************************************
+ * Display Device Class API definition
+ *****************************************************************************/
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenDCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseDCDevice(IMG_CONST PVRSRV_CONNECTION	*psConnection, IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCFormats (IMG_HANDLE hDevice,
+											IMG_UINT32		*pui32Count,
+											DISPLAY_FORMAT	*psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCDims (IMG_HANDLE hDevice,
+										IMG_UINT32 		*pui32Count,
+										DISPLAY_FORMAT	*psFormat,
+										DISPLAY_DIMS	*psDims);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCSystemBuffer(IMG_HANDLE hDevice,
+										IMG_HANDLE *phBuffer
+	);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCInfo(IMG_HANDLE hDevice,
+										DISPLAY_INFO* psDisplayInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDCSwapChain (IMG_HANDLE				hDevice,
+													IMG_UINT32				ui32Flags,
+													DISPLAY_SURF_ATTRIBUTES	*psDstSurfAttrib,
+													DISPLAY_SURF_ATTRIBUTES	*psSrcSurfAttrib,
+													IMG_UINT32				ui32BufferCount,
+													IMG_UINT32				ui32OEMFlags,
+													IMG_UINT32				*pui32SwapChainID,
+													IMG_HANDLE				*phSwapChain
+	);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDCSwapChain (IMG_HANDLE hDevice,
+											IMG_HANDLE		hSwapChain
+	);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstRect (IMG_HANDLE hDevice,
+										IMG_HANDLE	hSwapChain,
+										IMG_RECT	*psDstRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcRect (IMG_HANDLE hDevice,
+										IMG_HANDLE	hSwapChain,
+										IMG_RECT	*psSrcRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstColourKey (IMG_HANDLE hDevice,
+											IMG_HANDLE	hSwapChain,
+											IMG_UINT32	ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcColourKey (IMG_HANDLE hDevice,
+											IMG_HANDLE	hSwapChain,
+											IMG_UINT32	ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers(IMG_HANDLE hDevice,
+									IMG_HANDLE hSwapChain,
+									IMG_HANDLE *phBuffer
+	);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers2(IMG_HANDLE hDevice,
+											  IMG_HANDLE hSwapChain,
+											  IMG_HANDLE *phBuffer,
+											  IMG_SYS_PHYADDR *psPhyAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer (IMG_HANDLE hDevice,
+										IMG_HANDLE hBuffer,
+										IMG_UINT32 ui32ClipRectCount,
+										IMG_RECT  *psClipRect,
+										IMG_UINT32 ui32SwapInterval,
+										IMG_HANDLE hPrivateTag
+	);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer2 (IMG_HANDLE hDevice,
+										IMG_HANDLE hBuffer,
+										IMG_UINT32 ui32SwapInterval,
+										PVRSRV_CLIENT_MEM_INFO **ppsMemInfos,
+										PVRSRV_CLIENT_SYNC_INFO **ppsSyncInfos,
+										IMG_UINT32 ui32NumMemSyncInfos,
+										IMG_PVOID  pvPrivData,
+										IMG_UINT32 ui32PrivDataLength,
+										IMG_HANDLE *phFence);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+										IMG_HANDLE hSwapChain
+	);
+
+/******************************************************************************
+ * Buffer Device Class API definition
+ *****************************************************************************/
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenBCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseBCDevice(IMG_HANDLE hConnection,
+												IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBufferInfo(IMG_HANDLE hDevice,
+												BUFFER_INFO	*psBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBuffer(IMG_HANDLE hDevice,
+												IMG_UINT32 ui32BufferIndex,
+												IMG_HANDLE *phBuffer
+	);
+
+#endif /* #if defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+/******************************************************************************
+ * PDUMP Function prototypes...
+ *****************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(IMG_HANDLE hConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStartInitPhase(IMG_HANDLE hConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStopInitPhase(IMG_HANDLE hConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPol(IMG_HANDLE hConnection,
+										  PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+										  IMG_UINT32 ui32Offset,
+										  IMG_UINT32 ui32Value,
+										  IMG_UINT32 ui32Mask,
+										  PDUMP_POLL_OPERATOR eOperator,
+										  IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol(IMG_HANDLE hConnection,
+											 PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+											 IMG_BOOL   bIsRead,
+											 IMG_UINT32 ui32Value,
+											 IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol2(IMG_HANDLE hConnection,
+											 PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+											 IMG_BOOL bIsRead);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMem(IMG_HANDLE hConnection,
+									IMG_PVOID pvAltLinAddr,
+									PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+									IMG_UINT32 ui32Offset,
+									IMG_UINT32 ui32Bytes,
+									IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSync(IMG_HANDLE hConnection,
+										IMG_PVOID pvAltLinAddr,
+										PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+										IMG_UINT32 ui32Offset,
+										IMG_UINT32 ui32Bytes);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpReg(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+										 IMG_CHAR *pszRegRegion,
+											IMG_UINT32 ui32RegAddr,
+											IMG_UINT32 ui32RegValue,
+											IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPolWithFlags(const PVRSRV_DEV_DATA *psDevData,
+													 IMG_CHAR *pszRegRegion,
+													 IMG_UINT32 ui32RegAddr,
+													 IMG_UINT32 ui32RegValue,
+													 IMG_UINT32 ui32Mask,
+													 IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPol(const PVRSRV_DEV_DATA *psDevData,
+											IMG_CHAR *pszRegRegion,
+											IMG_UINT32 ui32RegAddr,
+											IMG_UINT32 ui32RegValue,
+											IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDReg(IMG_HANDLE hConnection,
+											IMG_UINT32 ui32RegAddr,
+											IMG_UINT32 ui32RegValue);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDDevPAddr(IMG_HANDLE hConnection,
+												PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+												IMG_UINT32 ui32Offset,
+												IMG_DEV_PHYADDR sPDDevPAddr);
+
+#if !defined(USE_CODE)
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPages(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+														   IMG_HANDLE			hKernelMemInfo,
+														   IMG_DEV_PHYADDR		*pPages,
+														   IMG_UINT32			ui32NumPages,
+												   		   IMG_DEV_VIRTADDR		sDevVAddr,
+														   IMG_UINT32			ui32Start,
+														   IMG_UINT32			ui32Length,
+														   IMG_UINT32			ui32Flags);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetFrame(IMG_HANDLE hConnection,
+											  IMG_UINT32 ui32Frame);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpComment(IMG_HANDLE hConnection,
+											 IMG_CONST IMG_CHAR *pszComment,
+											 IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentf(IMG_HANDLE hConnection,
+											  IMG_BOOL bContinuous,
+											  IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+											  IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(IMG_HANDLE hConnection,
+													   IMG_UINT32 ui32Flags,
+													   IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+													   IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpDriverInfo(IMG_HANDLE hConnection,
+								 				IMG_CHAR *pszString,
+												IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpIsCapturing(IMG_HANDLE hConnection,
+								 				IMG_BOOL *pbIsCapturing);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpBitmap(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+								 			IMG_CHAR *pszFileName,
+											IMG_UINT32 ui32FileOffset,
+											IMG_UINT32 ui32Width,
+											IMG_UINT32 ui32Height,
+											IMG_UINT32 ui32StrideInBytes,
+											IMG_DEV_VIRTADDR sDevBaseAddr,
+											IMG_HANDLE hDevMemContext,
+											IMG_UINT32 ui32Size,
+											PDUMP_PIXEL_FORMAT ePixelFormat,
+											PDUMP_MEM_FORMAT eMemFormat,
+											IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											IMG_CONST IMG_CHAR *pszRegRegion,
+								 			IMG_CONST IMG_CHAR *pszFileName,
+											IMG_UINT32 ui32FileOffset,
+											IMG_UINT32 ui32Address,
+											IMG_UINT32 ui32Size,
+											IMG_UINT32 ui32PDumpFlags);
+
+
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsCapturingTest(IMG_HANDLE hConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCycleCountRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+														IMG_UINT32 ui32RegOffset,
+														IMG_BOOL bLastFrame);
+
+IMG_IMPORT IMG_HANDLE	PVRSRVLoadLibrary(const IMG_CHAR *pszLibraryName);
+IMG_IMPORT PVRSRV_ERROR	PVRSRVUnloadLibrary(IMG_HANDLE hExtDrv);
+IMG_IMPORT PVRSRV_ERROR	PVRSRVGetLibFuncAddr(IMG_HANDLE hExtDrv, const IMG_CHAR *pszFunctionName, IMG_VOID **ppvFuncAddr);
+
+IMG_IMPORT IMG_UINT32 PVRSRVClockus (void);
+IMG_IMPORT IMG_VOID PVRSRVWaitus (IMG_UINT32 ui32Timeus);
+IMG_IMPORT IMG_VOID PVRSRVReleaseThreadQuanta (void);
+IMG_IMPORT IMG_UINT32 IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+IMG_IMPORT IMG_CHAR * IMG_CALLCONV PVRSRVSetLocale(const IMG_CHAR *pszLocale);
+
+
+
+
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVCreateAppHintState(IMG_MODULE_ID eModuleID,
+														const IMG_CHAR *pszAppName,
+														IMG_VOID **ppvState);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeAppHintState(IMG_MODULE_ID eModuleID,
+										 IMG_VOID *pvHintState);
+
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetAppHint(IMG_VOID			*pvHintState,
+												  const IMG_CHAR	*pszHintName,
+												  IMG_DATA_TYPE		eDataType,
+												  const IMG_VOID	*pvDefault,
+												  IMG_VOID			*pvReturn);
+
+/******************************************************************************
+ * Memory API(s)
+ *****************************************************************************/
+
+/* Exported APIs */
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T uiSize);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T uiSize);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uiNewSize);
+IMG_IMPORT IMG_VOID  IMG_CALLCONV PVRSRVFreeUserModeMem (IMG_PVOID pvMem);
+IMG_IMPORT IMG_VOID PVRSRVMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T uiSize);
+IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T uiSize);
+
+struct _PVRSRV_MUTEX_OPAQUE_STRUCT_;
+typedef	struct  _PVRSRV_MUTEX_OPAQUE_STRUCT_ *PVRSRV_MUTEX_HANDLE;
+
+
+#if defined(PVR_DEBUG_MUTEXES)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex,
+													   IMG_CHAR pszMutexName[],
+													   IMG_CHAR pszFilename[],
+													   IMG_INT iLine);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex,
+														IMG_CHAR pszMutexName[],
+														IMG_CHAR pszFilename[],
+														IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex,
+												 IMG_CHAR pszMutexName[],
+												 IMG_CHAR pszFilename[],
+												 IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex,
+												   IMG_CHAR pszMutexName[],
+												   IMG_CHAR pszFilename[],
+												   IMG_INT iLine);
+
+#define PVRSRVCreateMutex(phMutex) PVRSRVCreateMutex(phMutex, #phMutex, __FILE__, __LINE__)
+#define PVRSRVDestroyMutex(hMutex) PVRSRVDestroyMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVLockMutex(hMutex) PVRSRVLockMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVUnlockMutex(hMutex) PVRSRVUnlockMutex(hMutex, #hMutex, __FILE__, __LINE__)
+
+#else /* defined(PVR_DEBUG_MUTEXES) */
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+
+#endif /* defined(PVR_DEBUG_MUTEXES) */
+
+
+struct _PVRSRV_RECMUTEX_OPAQUE_STRUCT_;
+typedef	struct  _PVRSRV_RECMUTEX_OPAQUE_STRUCT_ *PVRSRV_RECMUTEX_HANDLE;
+
+
+#if defined(PVR_DEBUG_MUTEXES)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateRecursiveMutex(PVRSRV_RECMUTEX_HANDLE *phMutex,
+													   IMG_CHAR pszMutexName[],
+													   IMG_CHAR pszFilename[],
+													   IMG_INT iLine);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex,
+														IMG_CHAR pszMutexName[],
+														IMG_CHAR pszFilename[],
+														IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex,
+												 IMG_CHAR pszMutexName[],
+												 IMG_CHAR pszFilename[],
+												 IMG_INT iLine);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex,
+												   IMG_CHAR pszMutexName[],
+												   IMG_CHAR pszFilename[],
+												   IMG_INT iLine);
+
+#define PVRSRVCreateRecursiveMutex(phMutex) PVRSRVCreateRecursiveMutex(phMutex, #phMutex, __FILE__, __LINE__)
+#define PVRSRVDestroyRecursiveMutex(hMutex) PVRSRVDestroyRecursiveMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVLockRecursiveMutex(hMutex) PVRSRVLockRecursiveMutex(hMutex, #hMutex, __FILE__, __LINE__)
+#define PVRSRVUnlockRecursiveMutex(hMutex) PVRSRVUnlockRecursiveMutex(hMutex, #hMutex, __FILE__, __LINE__)
+
+#else /* defined(PVR_DEBUG_MUTEXES) */
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateRecursiveMutex(PVRSRV_RECMUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockRecursiveMutex(PVRSRV_RECMUTEX_HANDLE hMutex);
+
+#endif /* defined(PVR_DEBUG_MUTEXES) */
+
+/* Non-recursive coarse-grained mutex shared between all threads in a proccess */
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockProcessGlobalMutex(void);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockProcessGlobalMutex(void);
+
+
+struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_;
+typedef	struct  _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_ *PVRSRV_SEMAPHORE_HANDLE;
+
+
+  	#define IMG_SEMAPHORE_WAIT_INFINITE       ((IMG_UINT64)0xFFFFFFFFFFFFFFFFull)
+
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCreateSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVCreateSemaphore(PVRSRV_SEMAPHORE_HANDLE *phSemaphore, IMG_INT iInitialCount)
+{
+	PVR_UNREFERENCED_PARAMETER(iInitialCount);
+	*phSemaphore = 0;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVDestroySemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVDestroySemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore)
+{
+	PVR_UNREFERENCED_PARAMETER(hSemaphore);
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVWaitSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVWaitSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_UINT64 ui64TimeoutMicroSeconds)
+{
+	PVR_UNREFERENCED_PARAMETER(hSemaphore);
+	PVR_UNREFERENCED_PARAMETER(ui64TimeoutMicroSeconds);
+	return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPostSemaphore)
+#endif
+static INLINE IMG_VOID PVRSRVPostSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_INT iPostCount)
+{
+	PVR_UNREFERENCED_PARAMETER(hSemaphore);
+	PVR_UNREFERENCED_PARAMETER(iPostCount);
+}
+
+#endif /* !defined(USE_CODE) */
+
+
+/* Non-exported APIs */
+#if defined(DEBUG) && (defined(__linux__) || defined(__QNXNTO__) )
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_VOID  IMG_CALLCONV PVRSRVFreeUserModeMemTracking(IMG_VOID *pvMem);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem, IMG_SIZE_T ui32NewSize, 
+													  IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+#endif
+
+/******************************************************************************
+ * PVR Event Object API(s)
+ *****************************************************************************/
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
+									IMG_HANDLE hOSEvent
+	);
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVCreateSyncInfoModObj
+
+ @Description	Creates an empty Modification object to be later used by PVRSRVModifyPendingSyncOps
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateSyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+													 IMG_HANDLE *phKernelSyncInfoModObj
+	);
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVDestroySyncInfoModObj
+
+ @Description	Destroys a Modification object.  Must be empty.
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroySyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+													  IMG_HANDLE hKernelSyncInfoModObj
+	);
+
+
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVModifyPendingSyncOps
+
+ @Description	Returns PRE-INCREMENTED sync op values. Performs thread safe increment
+				of sync ops values as specified by ui32ModifyFlags.
+
+				PVRSRV_ERROR_RETRY is returned if the supplied modification object
+                is not empty.  This is on the assumption that a different thread
+				will imminently call PVRSRVModifyCompleteSyncOps.  This thread should
+				sleep before retrying.  It should be regarded as an error if no such
+				other thread exists.
+
+				Note that this API has implied locking semantics, as follows:
+
+				PVRSRVModifyPendingSyncOps() 
+				        -  announces an operation on the buffer is "pending", and 
+						   conceptually takes a ticket to represent your place in the queue.
+						-  NB: ** exclusive access to the resource is  _NOT_ granted at this time **
+				PVRSRVSyncOpsFlushToModObj()
+				        -  ensures you have exclusive access to the resource (conceptually, a LOCK)
+						-  the previously "pending" operation can now be regarded as "in progress"
+				PVRSRVModifyCompleteSyncOps()
+				        -  declares that the previously "in progress" operation is now complete. (UNLOCK)
+				
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyPendingSyncOps(const PVRSRV_CONNECTION *psConnection,
+													  IMG_HANDLE hKernelSyncInfoModObj,
+													  PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+													  IMG_UINT32 ui32ModifyFlags,
+													  IMG_UINT32 *pui32ReadOpsPending,
+													  IMG_UINT32 *pui32WriteOpsPending);
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVModifyCompleteSyncOps
+
+ @Description	Performs thread safe increment of sync ops values as specified
+                by the ui32ModifyFlags that were given to PVRSRVModifyPendingSyncOps.
+				The supplied Modification Object will become empty.
+
+				Note that this API has implied locking semantics, as
+				described above in PVRSRVModifyPendingSyncOps
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyCompleteSyncOps(const PVRSRV_CONNECTION *psConnection,
+													  IMG_HANDLE hKernelSyncInfoModObj
+	);
+
+/*!
+ ******************************************************************************
+
+ @Function	PVRSRVSyncOpsTakeToken
+
+ @Description Takes a "deli-counter" style token for future use with
+              PVRSRVSyncOpsFlushToToken().  In practice this means
+              recording a snapshot of the current "pending" values.  A
+              future PVRSRVSyncOpsFlushToToken() will ensure that all
+              operations that were pending at the time of this
+              PVRSRVSyncOpsTakeToken() call will be flushed.
+              Operations may be subsequently queued after this call
+              and would not be flushed.  The caller is required to
+              provide storage for the token.  The token is disposable
+              - i.e. the caller can simply let the token go out of
+              scope without telling us... in particular, there is no
+              obligation to call PVRSRVSyncOpsFlushToToken().
+              Multiple tokens may be taken.  There is no implied
+              locking with this API.
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsTakeToken(const PVRSRV_CONNECTION *psConnection,
+												 const PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+												 PVRSRV_SYNC_TOKEN *psSyncToken);
+/*!
+ ******************************************************************************
+
+ @Function	PVRSRVSyncOpsFlushToToken
+
+ @Description Tests whether the dependencies for a pending sync op modification
+              have been satisfied.  If this function returns PVRSRV_OK, then the
+              "complete" counts have caught up with the snapshot of the "pending"
+              values taken when PVRSRVSyncOpsTakeToken() was called.
+              In the event that the dependencies are not (yet) met,
+			  this call will auto-retry if bWait is specified, otherwise, it will
+			  return PVRSRV_ERROR_RETRY.  (Not really an "error")
+
+			  (auto-retry behaviour not implemented)
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToToken(const PVRSRV_CONNECTION *psConnection,
+													const PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+													const PVRSRV_SYNC_TOKEN *psSyncToken,
+													IMG_BOOL bWait);
+/*!
+ ******************************************************************************
+
+ @Function	PVRSRVSyncOpsFlushToModObj
+
+ @Description Tests whether the dependencies for a pending sync op modification
+              have been satisfied.  If this function returns PVRSRV_OK, then the
+              "complete" counts have caught up with the snapshot of the "pending"
+              values taken when PVRSRVModifyPendingSyncOps() was called.
+              PVRSRVModifyCompleteSyncOps() can then be called without risk of
+			  stalling.  In the event that the dependencies are not (yet) met,
+			  this call will auto-retry if bWait is specified, otherwise, it will
+			  return PVRSRV_ERROR_RETRY.  (Not really an "error")
+
+			  Note that this API has implied locking semantics, as
+			  described above in PVRSRVModifyPendingSyncOps
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToModObj(const PVRSRV_CONNECTION *psConnection,
+													 IMG_HANDLE hKernelSyncInfoModObj,
+													 IMG_BOOL bWait);
+
+/*!
+ ******************************************************************************
+
+ @Function	PVRSRVSyncOpsFlushToDelta
+
+ @Description Compares the number of outstanding operations (pending count minus
+              complete count) with the limit specified.  If no more than ui32Delta
+              operations are outstanding, this function returns PVRSRV_OK.
+              In the event that there are too many outstanding operations,
+			  this call will auto-retry if bWait is specified, otherwise, it will
+			  return PVRSRV_ERROR_RETRY.  (Not really an "error")
+
+ ******************************************************************************/
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToDelta(const PVRSRV_CONNECTION *psConnection,
+													PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+													IMG_UINT32 ui32Delta,
+													IMG_BOOL bWait);
+
+/*!
+ ******************************************************************************
+
+ @Function	PVRSRVAllocSyncInfo
+
+ @Description Creates a Sync Object.  Unlike the sync objects created
+			  automatically with "PVRSRVAllocDeviceMem", the sync objects
+			  returned by this function do _not_ have a UM mapping to the
+			  sync data and they do _not_ have the device virtual address
+			  of the "opscomplete" fields.  These data are to be deprecated.
+
+ ******************************************************************************/
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfo(IMG_CONST PVRSRV_DEV_DATA	*psDevData,
+											  PVRSRV_CLIENT_SYNC_INFO **ppsSyncInfo);
+
+/*!
+ ******************************************************************************
+
+ @Function	PVRSRVFreeSyncInfo
+
+ @Description Destroys a Sync Object created via
+              PVRSRVAllocSyncInfo.
+
+ ******************************************************************************/
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+											 PVRSRV_CLIENT_SYNC_INFO *psSyncInfo);
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVGetErrorString
+
+ @Description	Returns a text string relating to the PVRSRV_ERROR enum.
+
+ ******************************************************************************/
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError);
+
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVCacheInvalidate
+
+ @Description   Invalidate the CPU cache for a specified memory
+                area. Note that PVRSRVGetMiscInfo provides similar cpu
+                cache flush/invalidate functionality for some platforms.
+
+ ******************************************************************************/
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCacheInvalidate(const PVRSRV_CONNECTION *psConnection,
+                                                IMG_PVOID pvLinearAddress,
+	                                            IMG_UINT32 ui32Size);
+
+/******************************************************************************
+ Time wrapping macro
+******************************************************************************/
+#define TIME_NOT_PASSED_UINT32(a,b,c)		(((a) - (b)) < (c))
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __SERVICES_H__ */
+
+/******************************************************************************
+ End of file (services.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/include4/servicesext.h b/drivers/gpu/pvr/include4/servicesext.h
new file mode 100644
index 0000000..bde9caf
--- /dev/null
+++ b/drivers/gpu/pvr/include4/servicesext.h
@@ -0,0 +1,980 @@
+/*************************************************************************/ /*!
+@Title          Services definitions required by external drivers
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provides services data structures, defines and prototypes
+                required by external drivers.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+/*
+ * Lock buffer read/write flags
+ */
+#define PVRSRV_LOCKFLG_READONLY     	(1)		/*!< The locking process will only read the locked surface */
+
+/*!
+ *****************************************************************************
+ * Error values
+ *
+ * NOTE: If you change this, make sure you update the error texts in
+ *   services4/include/pvrsrv_errors.h to match.
+ *
+ *****************************************************************************/
+typedef enum _PVRSRV_ERROR_
+{
+	PVRSRV_OK = 0,
+	PVRSRV_ERROR_OUT_OF_MEMORY,
+	PVRSRV_ERROR_TOO_FEW_BUFFERS,
+	PVRSRV_ERROR_INVALID_PARAMS,
+	PVRSRV_ERROR_INIT_FAILURE,
+	PVRSRV_ERROR_CANT_REGISTER_CALLBACK,
+	PVRSRV_ERROR_INVALID_DEVICE,
+	PVRSRV_ERROR_NOT_OWNER,
+	PVRSRV_ERROR_BAD_MAPPING,
+	PVRSRV_ERROR_TIMEOUT,
+	PVRSRV_ERROR_FLIP_CHAIN_EXISTS,
+	PVRSRV_ERROR_INVALID_SWAPINTERVAL,
+	PVRSRV_ERROR_SCENE_INVALID,
+	PVRSRV_ERROR_STREAM_ERROR,
+	PVRSRV_ERROR_FAILED_DEPENDENCIES,
+	PVRSRV_ERROR_CMD_NOT_PROCESSED,
+	PVRSRV_ERROR_CMD_TOO_BIG,
+	PVRSRV_ERROR_DEVICE_REGISTER_FAILED,
+	PVRSRV_ERROR_TOOMANYBUFFERS,
+	PVRSRV_ERROR_NOT_SUPPORTED,
+	PVRSRV_ERROR_PROCESSING_BLOCKED,
+
+	PVRSRV_ERROR_CANNOT_FLUSH_QUEUE,
+	PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE,
+	PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS,
+	PVRSRV_ERROR_RETRY,
+
+	PVRSRV_ERROR_DDK_VERSION_MISMATCH,
+	PVRSRV_ERROR_BUILD_MISMATCH,
+	PVRSRV_ERROR_CORE_REVISION_MISMATCH,
+
+	PVRSRV_ERROR_UPLOAD_TOO_BIG,
+
+	PVRSRV_ERROR_INVALID_FLAGS,
+	PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS,
+
+	PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY,
+	PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR,
+	PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED,
+
+	PVRSRV_ERROR_BRIDGE_CALL_FAILED,
+	PVRSRV_ERROR_IOCTL_CALL_FAILED,
+
+    PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND,
+	PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND,
+	PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT,
+
+	PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND,
+	PVRSRV_ERROR_PCI_CALL_FAILED,
+	PVRSRV_ERROR_PCI_REGION_TOO_SMALL,
+	PVRSRV_ERROR_PCI_REGION_UNAVAILABLE,
+	PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH,
+
+	PVRSRV_ERROR_REGISTER_BASE_NOT_SET,
+
+    PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE,
+
+	PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM,
+	PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY,
+	PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC,
+	PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR,
+
+	PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY,
+	PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY,
+
+	PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES,
+	PVRSRV_ERROR_FAILED_TO_FREE_PAGES,
+	PVRSRV_ERROR_FAILED_TO_COPY_PAGES,
+	PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES,
+	PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES,
+	PVRSRV_ERROR_STILL_MAPPED,
+	PVRSRV_ERROR_MAPPING_NOT_FOUND,
+	PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT,
+	PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE,
+
+	PVRSRV_ERROR_INVALID_SEGMENT_BLOCK,
+	PVRSRV_ERROR_INVALID_SGXDEVDATA,
+	PVRSRV_ERROR_INVALID_DEVINFO,
+	PVRSRV_ERROR_INVALID_MEMINFO,
+	PVRSRV_ERROR_INVALID_MISCINFO,
+	PVRSRV_ERROR_UNKNOWN_IOCTL,
+	PVRSRV_ERROR_INVALID_CONTEXT,
+	PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT,
+	PVRSRV_ERROR_INVALID_HEAP,
+	PVRSRV_ERROR_INVALID_KERNELINFO,
+	PVRSRV_ERROR_UNKNOWN_POWER_STATE,
+	PVRSRV_ERROR_INVALID_HANDLE_TYPE,
+	PVRSRV_ERROR_INVALID_WRAP_TYPE,
+	PVRSRV_ERROR_INVALID_PHYS_ADDR,
+	PVRSRV_ERROR_INVALID_CPU_ADDR,
+	PVRSRV_ERROR_INVALID_HEAPINFO,
+	PVRSRV_ERROR_INVALID_PERPROC,
+	PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO,
+	PVRSRV_ERROR_INVALID_MAP_REQUEST,
+	PVRSRV_ERROR_INVALID_UNMAP_REQUEST,
+	PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP,
+	PVRSRV_ERROR_MAPPING_STILL_IN_USE,
+
+	PVRSRV_ERROR_EXCEEDED_HW_LIMITS,
+	PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED,
+
+	PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA,
+	PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT,
+	PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT,
+	PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT,
+	PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT,
+	PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD,
+	PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD,
+	PVRSRV_ERROR_THREAD_READ_ERROR,
+	PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER,
+	PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR,
+	PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR,
+	PVRSRV_ERROR_ISR_ALREADY_INSTALLED,
+	PVRSRV_ERROR_ISR_NOT_INSTALLED,
+	PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT,
+	PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO,
+	PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT,
+	PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES,
+	PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT,
+	PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE,
+	PVRSRV_ERROR_UNABLE_TO_CLOSE_HANDLE,
+
+	PVRSRV_ERROR_INVALID_CCB_COMMAND,
+
+	PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE,
+	PVRSRV_ERROR_INVALID_LOCK_ID,
+	PVRSRV_ERROR_RESOURCE_NOT_LOCKED,
+
+	PVRSRV_ERROR_FLIP_FAILED,
+	PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED,
+
+	PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE,
+
+	PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED,
+	PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG,
+	PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG,
+	PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG,
+
+	PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID,
+
+	PVRSRV_ERROR_BLIT_SETUP_FAILED,
+
+	PVRSRV_ERROR_PDUMP_NOT_AVAILABLE,
+	PVRSRV_ERROR_PDUMP_BUFFER_FULL,
+	PVRSRV_ERROR_PDUMP_BUF_OVERFLOW,
+	PVRSRV_ERROR_PDUMP_NOT_ACTIVE,
+	PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES,
+
+	PVRSRV_ERROR_MUTEX_DESTROY_FAILED,
+	PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR,
+
+	PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE,
+	PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND,
+
+	PVRSRV_ERROR_PROCESS_NOT_INITIALISED,
+	PVRSRV_ERROR_PROCESS_NOT_FOUND,
+	PVRSRV_ERROR_SRV_CONNECT_FAILED,
+	PVRSRV_ERROR_SRV_DISCONNECT_FAILED,
+	PVRSRV_ERROR_DEINT_PHASE_FAILED,
+	PVRSRV_ERROR_INIT2_PHASE_FAILED,
+
+	PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE,
+
+	PVRSRV_ERROR_NO_DC_DEVICES_FOUND,
+	PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE,
+	PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE,
+	PVRSRV_ERROR_NO_DEVICEDATA_FOUND,
+	PVRSRV_ERROR_NO_DEVICENODE_FOUND,
+	PVRSRV_ERROR_NO_CLIENTNODE_FOUND,
+	PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE,
+
+	PVRSRV_ERROR_UNABLE_TO_INIT_TASK,
+	PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK,
+	PVRSRV_ERROR_UNABLE_TO_KILL_TASK,
+
+	PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER,
+	PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER,
+	PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER,
+
+	PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT,
+	PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION,
+
+	PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE,
+	PVRSRV_ERROR_HANDLE_NOT_ALLOCATED,
+	PVRSRV_ERROR_HANDLE_TYPE_MISMATCH,
+	PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE,
+	PVRSRV_ERROR_HANDLE_NOT_SHAREABLE,
+	PVRSRV_ERROR_HANDLE_NOT_FOUND,
+	PVRSRV_ERROR_INVALID_SUBHANDLE,
+	PVRSRV_ERROR_HANDLE_BATCH_IN_USE,
+	PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE,
+
+	PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE,
+	PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED,
+
+	PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE,
+	PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP,
+
+	PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE,
+
+	PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE,
+	PVRSRV_ERROR_INVALID_DEVICEID,
+	PVRSRV_ERROR_DEVICEID_NOT_FOUND,
+
+	PVRSRV_ERROR_MEMORY_TEST_FAILED,
+	PVRSRV_ERROR_CPUPADDR_TEST_FAILED,
+	PVRSRV_ERROR_COPY_TEST_FAILED,
+
+	PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED,
+
+	PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK,
+	PVRSRV_ERROR_CLOCK_REQUEST_FAILED,
+	PVRSRV_ERROR_DISABLE_CLOCK_FAILURE,
+	PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE,
+	PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE,
+	PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK,
+	PVRSRV_ERROR_UNABLE_TO_GET_CLOCK,
+	PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK,
+	PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK,
+
+	PVRSRV_ERROR_UNKNOWN_SGL_ERROR,
+
+	PVRSRV_ERROR_SYSTEM_POWER_CHANGE_FAILURE,
+	PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE,
+
+	PVRSRV_ERROR_BAD_SYNC_STATE,
+
+	PVRSRV_ERROR_CACHEOP_FAILED,
+
+	PVRSRV_ERROR_CACHE_INVALIDATE_FAILED,
+
+	PVRSRV_ERROR_TASK_FAILED,
+
+	PVRSRV_ERROR_NOT_READY,
+
+	PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+
+/*!
+ *****************************************************************************
+ * List of known device classes.
+ *****************************************************************************/
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+	PVRSRV_DEVICE_CLASS_3D				= 0 ,
+	PVRSRV_DEVICE_CLASS_DISPLAY			= 1 ,
+	PVRSRV_DEVICE_CLASS_BUFFER			= 2 ,
+	PVRSRV_DEVICE_CLASS_VIDEO			= 3 ,
+
+	PVRSRV_DEVICE_CLASS_FORCE_I32 		= 0x7fffffff
+
+} PVRSRV_DEVICE_CLASS;
+
+
+/*!
+ *****************************************************************************
+ *	States for power management
+ *****************************************************************************/
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+	PVRSRV_SYS_POWER_STATE_Unspecified		= -1,	/*!< Unspecified : Uninitialised */
+	PVRSRV_SYS_POWER_STATE_D0				= 0,	/*!< On */
+	PVRSRV_SYS_POWER_STATE_D1				= 1,	/*!< User Idle */
+	PVRSRV_SYS_POWER_STATE_D2				= 2,	/*!< System Idle / sleep */
+	PVRSRV_SYS_POWER_STATE_D3				= 3,	/*!< Suspend / Hibernate */
+	PVRSRV_SYS_POWER_STATE_D4				= 4,	/*!< shutdown */
+
+	PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE;
+
+
+typedef enum _PVRSRV_DEV_POWER_STATE_
+{
+	PVRSRV_DEV_POWER_STATE_DEFAULT	= -1,	/*!< Default state for the device */
+	PVRSRV_DEV_POWER_STATE_ON		= 0,	/*!< Running */
+	PVRSRV_DEV_POWER_STATE_IDLE		= 1,	/*!< Powered but operation paused */
+	PVRSRV_DEV_POWER_STATE_OFF		= 2,	/*!< Unpowered */
+
+	PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;	/* PRQA S 3205 */
+
+
+/* Power transition handler prototypes */
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE				hDevHandle,
+									   PVRSRV_DEV_POWER_STATE	eNewPowerState,
+									   PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE				hDevHandle,
+										PVRSRV_DEV_POWER_STATE	eNewPowerState,
+										PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+/* Clock speed handler prototypes */
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE				hDevHandle,
+												   IMG_BOOL					bIdleDevice,
+												   PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE				hDevHandle,
+													IMG_BOOL				bIdleDevice,
+													PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+
+/*****************************************************************************
+ * Enumeration of all possible pixel types. Where applicable, Ordering of name
+ * is in reverse order of memory bytes (i.e. as a word in little endian).
+ * e.g. A8R8G8B8 is in memory as 4 bytes in order: BB GG RR AA
+ *
+ * NOTE: When modifying this structure please update the client driver format
+ *       tables located in %WORKROOT%/eurasia/codegen/pixfmts using the tool
+ *       located in %WORKROOT%/eurasia/tools/intern/TextureFormatParser.
+ *
+ *****************************************************************************/
+typedef enum _PVRSRV_PIXEL_FORMAT_ {
+	/* Basic types */
+	PVRSRV_PIXEL_FORMAT_UNKNOWN				=  0,
+	PVRSRV_PIXEL_FORMAT_RGB565				=  1,
+	PVRSRV_PIXEL_FORMAT_RGB555				=  2,
+	PVRSRV_PIXEL_FORMAT_RGB888				=  3,	/*!< 24bit */
+	PVRSRV_PIXEL_FORMAT_BGR888				=  4,	/*!< 24bit */
+	PVRSRV_PIXEL_FORMAT_GREY_SCALE			=  8,
+	PVRSRV_PIXEL_FORMAT_PAL12				= 13,
+	PVRSRV_PIXEL_FORMAT_PAL8				= 14,
+	PVRSRV_PIXEL_FORMAT_PAL4				= 15,
+	PVRSRV_PIXEL_FORMAT_PAL2				= 16,
+	PVRSRV_PIXEL_FORMAT_PAL1				= 17,
+	PVRSRV_PIXEL_FORMAT_ARGB1555			= 18,
+	PVRSRV_PIXEL_FORMAT_ARGB4444			= 19,
+	PVRSRV_PIXEL_FORMAT_ARGB8888			= 20,
+	PVRSRV_PIXEL_FORMAT_ABGR8888			= 21,
+	PVRSRV_PIXEL_FORMAT_YV12				= 22,
+	PVRSRV_PIXEL_FORMAT_I420				= 23,
+    PVRSRV_PIXEL_FORMAT_IMC2				= 25,
+	PVRSRV_PIXEL_FORMAT_XRGB8888			= 26,
+	PVRSRV_PIXEL_FORMAT_XBGR8888			= 27,
+	PVRSRV_PIXEL_FORMAT_BGRA8888			= 28,
+	PVRSRV_PIXEL_FORMAT_XRGB4444			= 29,
+	PVRSRV_PIXEL_FORMAT_ARGB8332			= 30,
+	PVRSRV_PIXEL_FORMAT_A2RGB10				= 31,	/*!< 32bpp, 10 bits for R, G, B, 2 bits for A */
+	PVRSRV_PIXEL_FORMAT_A2BGR10				= 32,	/*!< 32bpp, 10 bits for B, G, R, 2 bits for A */
+	PVRSRV_PIXEL_FORMAT_P8					= 33,
+	PVRSRV_PIXEL_FORMAT_L8					= 34,
+	PVRSRV_PIXEL_FORMAT_A8L8				= 35,
+	PVRSRV_PIXEL_FORMAT_A4L4				= 36,
+	PVRSRV_PIXEL_FORMAT_L16					= 37,
+	PVRSRV_PIXEL_FORMAT_L6V5U5				= 38,
+	PVRSRV_PIXEL_FORMAT_V8U8				= 39,
+	PVRSRV_PIXEL_FORMAT_V16U16				= 40,
+	PVRSRV_PIXEL_FORMAT_QWVU8888			= 41,
+	PVRSRV_PIXEL_FORMAT_XLVU8888			= 42,
+	PVRSRV_PIXEL_FORMAT_QWVU16				= 43,
+	PVRSRV_PIXEL_FORMAT_D16					= 44,
+	PVRSRV_PIXEL_FORMAT_D24S8				= 45,
+	PVRSRV_PIXEL_FORMAT_D24X8				= 46,
+
+	/* Added to ensure TQ build */
+	PVRSRV_PIXEL_FORMAT_ABGR16				= 47,
+	PVRSRV_PIXEL_FORMAT_ABGR16F				= 48,
+	PVRSRV_PIXEL_FORMAT_ABGR32				= 49,
+	PVRSRV_PIXEL_FORMAT_ABGR32F				= 50,
+	PVRSRV_PIXEL_FORMAT_B10GR11				= 51,
+	PVRSRV_PIXEL_FORMAT_GR88				= 52,
+	PVRSRV_PIXEL_FORMAT_BGR32				= 53,
+	PVRSRV_PIXEL_FORMAT_GR32				= 54,
+	PVRSRV_PIXEL_FORMAT_E5BGR9				= 55,
+
+	/* reserved types */
+	PVRSRV_PIXEL_FORMAT_RESERVED1			= 56,
+	PVRSRV_PIXEL_FORMAT_RESERVED2			= 57,
+	PVRSRV_PIXEL_FORMAT_RESERVED3			= 58,
+	PVRSRV_PIXEL_FORMAT_RESERVED4			= 59,
+	PVRSRV_PIXEL_FORMAT_RESERVED5			= 60,
+
+	/* RGB space packed formats */
+	PVRSRV_PIXEL_FORMAT_R8G8_B8G8			= 61,
+	PVRSRV_PIXEL_FORMAT_G8R8_G8B8			= 62,
+
+	/* YUV space planar formats */
+	PVRSRV_PIXEL_FORMAT_NV11				= 63,
+	PVRSRV_PIXEL_FORMAT_NV12				= 64,
+
+	/* YUV space packed formats */
+	PVRSRV_PIXEL_FORMAT_YUY2				= 65,
+	PVRSRV_PIXEL_FORMAT_YUV420				= 66,
+	PVRSRV_PIXEL_FORMAT_YUV444				= 67,
+	PVRSRV_PIXEL_FORMAT_VUY444				= 68,
+	PVRSRV_PIXEL_FORMAT_YUYV				= 69,
+	PVRSRV_PIXEL_FORMAT_YVYU				= 70,
+	PVRSRV_PIXEL_FORMAT_UYVY				= 71,
+	PVRSRV_PIXEL_FORMAT_VYUY				= 72,
+
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY		= 73,	/*!< See http://www.fourcc.org/yuv.php#UYVY */
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV		= 74,	/*!< See http://www.fourcc.org/yuv.php#YUYV */
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU		= 75,	/*!< See http://www.fourcc.org/yuv.php#YVYU */
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY		= 76,	/*!< No fourcc.org link */
+	PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV		= 77,	/*!< See http://www.fourcc.org/yuv.php#AYUV */
+
+	/* 4 component, 32 bits per component types */
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32		= 78,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32F		= 79,	/*!< float type */
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT	= 80,	/*!< uint type */
+	PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT	= 81,	/*!< sint type */
+
+	/* 3 component, 32 bits per component types */
+	PVRSRV_PIXEL_FORMAT_B32G32R32			= 82,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_B32G32R32F			= 83,	/*!< float data */
+	PVRSRV_PIXEL_FORMAT_B32G32R32_UINT		= 84,	/*!< uint data */
+	PVRSRV_PIXEL_FORMAT_B32G32R32_SINT		= 85,	/*!< signed int data */
+
+	/* 2 component, 32 bits per component types */
+	PVRSRV_PIXEL_FORMAT_G32R32				= 86,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_G32R32F				= 87,	/*!< float */
+	PVRSRV_PIXEL_FORMAT_G32R32_UINT			= 88,	/*!< uint */
+	PVRSRV_PIXEL_FORMAT_G32R32_SINT			= 89,	/*!< signed int */
+
+	/* 1 component, 32 bits per component types */
+	PVRSRV_PIXEL_FORMAT_D32F				= 90,	/*!< float depth */
+	PVRSRV_PIXEL_FORMAT_R32					= 91,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_R32F				= 92,	/*!< float type */
+	PVRSRV_PIXEL_FORMAT_R32_UINT			= 93,	/*!< unsigned int type */
+	PVRSRV_PIXEL_FORMAT_R32_SINT			= 94,	/*!< signed int type */
+
+	/* 4 component, 16 bits per component types */
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16		= 95,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16F		= 96,	/*!< type float */
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT	= 97,	/*!< signed ints */
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM	= 98,	/*!< signed normalised int */
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT	= 99,	/*!< unsigned ints */
+	PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM	= 100,	/*!< normalised unsigned int */
+
+	/* 2 component, 16 bits per component types */
+	PVRSRV_PIXEL_FORMAT_G16R16				= 101,	/*!< unspecified type */
+	PVRSRV_PIXEL_FORMAT_G16R16F				= 102,	/*!< float type */
+	PVRSRV_PIXEL_FORMAT_G16R16_UINT			= 103,	/*!< unsigned int type */
+	PVRSRV_PIXEL_FORMAT_G16R16_UNORM		= 104,	/*!< unsigned normalised */
+	PVRSRV_PIXEL_FORMAT_G16R16_SINT			= 105,	/*!< signed int  */
+	PVRSRV_PIXEL_FORMAT_G16R16_SNORM		= 106,	/*!< signed normalised */
+
+	/* 1 component, 16 bits per component types */
+	PVRSRV_PIXEL_FORMAT_R16					= 107,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_R16F				= 108,	/*!< float type */
+	PVRSRV_PIXEL_FORMAT_R16_UINT			= 109,	/*!< unsigned int type */
+	PVRSRV_PIXEL_FORMAT_R16_UNORM			= 110,	/*!< unsigned normalised int type */
+	PVRSRV_PIXEL_FORMAT_R16_SINT			= 111,	/*!< signed int type */
+	PVRSRV_PIXEL_FORMAT_R16_SNORM			= 112,	/*!< signed normalised int type */
+
+	/* 4 component, 8 bits per component types */
+	PVRSRV_PIXEL_FORMAT_X8R8G8B8			= 113,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM		= 114,	/*!< normalised unsigned int */
+	PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB	= 115,	/*!< normalised uint with sRGB */
+
+	PVRSRV_PIXEL_FORMAT_A8R8G8B8			= 116,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM		= 117,	/*!< normalised unsigned int */
+	PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB	= 118,	/*!< normalised uint with sRGB */
+
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8			= 119,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT		= 120,	/*!< unsigned int */
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM		= 121,	/*!< normalised unsigned int */
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB	= 122,	/*!< normalised unsigned int */
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT		= 123,	/*!< signed int */
+	PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM		= 124,	/*!< normalised signed int */
+
+	/* 2 component, 8 bits per component types */
+	PVRSRV_PIXEL_FORMAT_G8R8				= 125,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_G8R8_UINT			= 126,	/*!< unsigned int type */
+	PVRSRV_PIXEL_FORMAT_G8R8_UNORM			= 127,	/*!< unsigned int normalised */
+	PVRSRV_PIXEL_FORMAT_G8R8_SINT			= 128,	/*!< signed int type */
+	PVRSRV_PIXEL_FORMAT_G8R8_SNORM			= 129,	/*!< signed int normalised */
+
+	/* 1 component, 8 bits per component types */
+	PVRSRV_PIXEL_FORMAT_A8					= 130,	/*!< type unspecified, alpha channel */
+	PVRSRV_PIXEL_FORMAT_R8					= 131,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_R8_UINT				= 132,	/*!< unsigned int */
+	PVRSRV_PIXEL_FORMAT_R8_UNORM			= 133,	/*!< unsigned normalised int */
+	PVRSRV_PIXEL_FORMAT_R8_SINT				= 134,	/*!< signed int */
+	PVRSRV_PIXEL_FORMAT_R8_SNORM			= 135,	/*!< signed normalised int */
+
+	/* A2RGB10 types */
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10			= 136,	/*!< Type unspecified */
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM	= 137,	/*!< normalised unsigned int */
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT	= 138,	/*!< unsigned int */
+
+	/* F11F11F10 types */
+	PVRSRV_PIXEL_FORMAT_B10G11R11			= 139,	/*!< type unspecified */
+	PVRSRV_PIXEL_FORMAT_B10G11R11F			= 140,	/*!< float type */
+
+	/* esoteric types */
+	PVRSRV_PIXEL_FORMAT_X24G8R32			= 141,	/*!< 64 bit, type unspecified (Usually typed to D32S8 style) */
+	PVRSRV_PIXEL_FORMAT_G8R24				= 142,	/*!< 32 bit, type unspecified (Usually typed to D24S8 style) */
+	PVRSRV_PIXEL_FORMAT_X8R24				= 143,
+	PVRSRV_PIXEL_FORMAT_E5B9G9R9			= 144,	/*!< 32 bit, shared exponent (RGBE). */
+	PVRSRV_PIXEL_FORMAT_R1					= 145,	/*!< 1 bit monochrome */
+
+	PVRSRV_PIXEL_FORMAT_RESERVED6			= 146,
+	PVRSRV_PIXEL_FORMAT_RESERVED7			= 147,
+	PVRSRV_PIXEL_FORMAT_RESERVED8			= 148,
+	PVRSRV_PIXEL_FORMAT_RESERVED9			= 149,
+	PVRSRV_PIXEL_FORMAT_RESERVED10			= 150,
+	PVRSRV_PIXEL_FORMAT_RESERVED11			= 151,
+	PVRSRV_PIXEL_FORMAT_RESERVED12			= 152,
+	PVRSRV_PIXEL_FORMAT_RESERVED13			= 153,
+	PVRSRV_PIXEL_FORMAT_RESERVED14			= 154,
+	PVRSRV_PIXEL_FORMAT_RESERVED15			= 155,
+	PVRSRV_PIXEL_FORMAT_RESERVED16			= 156,
+	PVRSRV_PIXEL_FORMAT_RESERVED17			= 157,
+	PVRSRV_PIXEL_FORMAT_RESERVED18			= 158,
+	PVRSRV_PIXEL_FORMAT_RESERVED19			= 159,
+	PVRSRV_PIXEL_FORMAT_RESERVED20			= 160,
+
+	/* DXLegacy vertex types */
+	PVRSRV_PIXEL_FORMAT_UBYTE4				= 161,	/*!< 4 channels, 1 byte per channel, normalised */
+	PVRSRV_PIXEL_FORMAT_SHORT4				= 162,	/*!< 4 signed channels, 16 bits each, unnormalised */
+	PVRSRV_PIXEL_FORMAT_SHORT4N				= 163,	/*!< 4 signed channels, 16 bits each, normalised */
+	PVRSRV_PIXEL_FORMAT_USHORT4N			= 164,	/*!< 4 unsigned channels, 16 bits each, normalised */
+	PVRSRV_PIXEL_FORMAT_SHORT2N				= 165,	/*!< 2 signed channels, 16 bits each, normalised */
+	PVRSRV_PIXEL_FORMAT_SHORT2				= 166,	/*!< 2 signed channels, 16 bits each, unnormalised */
+	PVRSRV_PIXEL_FORMAT_USHORT2N			= 167,	/*!< 2 unsigned channels, 16 bits each, normalised */
+	PVRSRV_PIXEL_FORMAT_UDEC3				= 168,	/*!< 3 10-bit channels, unnormalised, unsigned*/
+	PVRSRV_PIXEL_FORMAT_DEC3N				= 169,	/*!< 3 10-bit channels, signed normalised */
+	PVRSRV_PIXEL_FORMAT_F16_2				= 170,	/*!< 2 F16 channels */
+	PVRSRV_PIXEL_FORMAT_F16_4				= 171,	/*!< 4 F16 channels */
+
+	/* misc float types */
+	PVRSRV_PIXEL_FORMAT_L_F16				= 172,
+	PVRSRV_PIXEL_FORMAT_L_F16_REP			= 173,
+	PVRSRV_PIXEL_FORMAT_L_F16_A_F16			= 174,
+	PVRSRV_PIXEL_FORMAT_A_F16				= 175,
+	PVRSRV_PIXEL_FORMAT_B16G16R16F			= 176,
+
+	PVRSRV_PIXEL_FORMAT_L_F32				= 177,
+	PVRSRV_PIXEL_FORMAT_A_F32				= 178,
+	PVRSRV_PIXEL_FORMAT_L_F32_A_F32			= 179,
+
+	/* powervr types */
+	PVRSRV_PIXEL_FORMAT_PVRTC2				= 180,
+	PVRSRV_PIXEL_FORMAT_PVRTC4				= 181,
+	PVRSRV_PIXEL_FORMAT_PVRTCII2			= 182,
+	PVRSRV_PIXEL_FORMAT_PVRTCII4			= 183,
+	PVRSRV_PIXEL_FORMAT_PVRTCIII			= 184,
+	PVRSRV_PIXEL_FORMAT_PVRO8				= 185,
+	PVRSRV_PIXEL_FORMAT_PVRO88				= 186,
+	PVRSRV_PIXEL_FORMAT_PT1					= 187,
+	PVRSRV_PIXEL_FORMAT_PT2					= 188,
+	PVRSRV_PIXEL_FORMAT_PT4					= 189,
+	PVRSRV_PIXEL_FORMAT_PT8					= 190,
+	PVRSRV_PIXEL_FORMAT_PTW					= 191,
+	PVRSRV_PIXEL_FORMAT_PTB					= 192,
+	PVRSRV_PIXEL_FORMAT_MONO8				= 193,
+	PVRSRV_PIXEL_FORMAT_MONO16				= 194,
+
+	/* additional YUV types */
+	PVRSRV_PIXEL_FORMAT_C0_YUYV				= 195,
+	PVRSRV_PIXEL_FORMAT_C0_UYVY				= 196,
+	PVRSRV_PIXEL_FORMAT_C0_YVYU				= 197,
+	PVRSRV_PIXEL_FORMAT_C0_VYUY				= 198,
+	PVRSRV_PIXEL_FORMAT_C1_YUYV				= 199,
+	PVRSRV_PIXEL_FORMAT_C1_UYVY				= 200,
+	PVRSRV_PIXEL_FORMAT_C1_YVYU				= 201,
+	PVRSRV_PIXEL_FORMAT_C1_VYUY				= 202,
+
+	/* planar YUV types */
+	PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV		= 203,
+	PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU		= 204,
+	PVRSRV_PIXEL_FORMAT_C0_YUV420_3P		= 205,
+	PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_UV		= 206,
+	PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_VU		= 207,
+	PVRSRV_PIXEL_FORMAT_C1_YUV420_3P		= 208,
+
+	PVRSRV_PIXEL_FORMAT_A2B10G10R10F		= 209,
+	PVRSRV_PIXEL_FORMAT_B8G8R8_SINT			= 210,
+	PVRSRV_PIXEL_FORMAT_PVRF32SIGNMASK		= 211,
+	
+	PVRSRV_PIXEL_FORMAT_ABGR4444			= 212,	
+	PVRSRV_PIXEL_FORMAT_ABGR1555			= 213,
+	PVRSRV_PIXEL_FORMAT_BGR565				= 214,			
+
+	/* 4k aligned planar YUV */
+	PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_UV	= 215,
+	PVRSRV_PIXEL_FORMAT_C0_4KYUV420_2P_VU	= 216,
+	PVRSRV_PIXEL_FORMAT_C1_4KYUV420_2P_UV	= 217,
+	PVRSRV_PIXEL_FORMAT_C1_4KYUV420_2P_VU	= 218,
+	PVRSRV_PIXEL_FORMAT_P208				= 219,			
+	PVRSRV_PIXEL_FORMAT_A8P8				= 220,			
+
+	PVRSRV_PIXEL_FORMAT_A4					= 221,
+	PVRSRV_PIXEL_FORMAT_AYUV8888			= 222,
+	PVRSRV_PIXEL_FORMAT_RAW256				= 223,
+	PVRSRV_PIXEL_FORMAT_RAW512				= 224,
+	PVRSRV_PIXEL_FORMAT_RAW1024				= 225,
+
+	/* Same as NV12 but with interleaved VU rather than interleaved UV */
+	PVRSRV_PIXEL_FORMAT_NV21				= 226,
+
+	/* Semi-planar version of YUYV */
+	PVRSRV_PIXEL_FORMAT_NV16				= 227,
+
+	PVRSRV_PIXEL_FORMAT_FORCE_I32			= 0x7fffffff
+
+} PVRSRV_PIXEL_FORMAT;
+
+/*!
+ *****************************************************************************
+ * Enumeration of possible alpha types.
+ *****************************************************************************/
+typedef enum _PVRSRV_ALPHA_FORMAT_ {
+	PVRSRV_ALPHA_FORMAT_UNKNOWN		=  0x00000000,
+	PVRSRV_ALPHA_FORMAT_PRE			=  0x00000001,
+	PVRSRV_ALPHA_FORMAT_NONPRE		=  0x00000002,
+	PVRSRV_ALPHA_FORMAT_MASK		=  0x0000000F
+} PVRSRV_ALPHA_FORMAT;
+
+/*!
+ *****************************************************************************
+ * Enumeration of possible alpha types.
+ *****************************************************************************/
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+	PVRSRV_COLOURSPACE_FORMAT_UNKNOWN		=  0x00000000,
+	PVRSRV_COLOURSPACE_FORMAT_LINEAR		=  0x00010000,
+	PVRSRV_COLOURSPACE_FORMAT_NONLINEAR		=  0x00020000,
+	PVRSRV_COLOURSPACE_FORMAT_MASK			=  0x000F0000
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+/*
+ * Drawable orientation (in degrees clockwise).
+ * Opposite sense from WSEGL.
+ */
+typedef enum _PVRSRV_ROTATION_ {
+	PVRSRV_ROTATE_0		=	0,
+	PVRSRV_ROTATE_90	=	1,
+	PVRSRV_ROTATE_180	=	2,
+	PVRSRV_ROTATE_270	=	3,
+	PVRSRV_FLIP_Y
+
+} PVRSRV_ROTATION;
+
+/*!
+ * Flags for DisplayClassCreateSwapChain.
+ */
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED		(1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY		(1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY	(1<<2)
+
+/*!
+ *****************************************************************************
+ * Structure providing implementation details for serialisation and
+ * synchronisation of operations. This is the fundamental unit on which operations
+ * are synced, and would typically be included in any data structures that require
+ * serialised accesses etc. e.g. MEM_INFO structures
+ *
+ *****************************************************************************/
+/*
+	Sync Data to be shared/mapped between user/kernel
+*/
+typedef struct _PVRSRV_SYNC_DATA_
+{
+	/* CPU accessible WriteOp Info */
+	IMG_UINT32					ui32WriteOpsPending;
+	volatile IMG_UINT32			ui32WriteOpsComplete;
+
+	/* CPU accessible ReadOp Info */
+	IMG_UINT32					ui32ReadOpsPending;
+	volatile IMG_UINT32			ui32ReadOpsComplete;
+
+	/* CPU accessible ReadOp2 Info */
+	IMG_UINT32					ui32ReadOps2Pending;
+	volatile IMG_UINT32			ui32ReadOps2Complete;
+
+	/* pdump specific value */
+	IMG_UINT32					ui32LastOpDumpVal;
+	IMG_UINT32					ui32LastReadOpDumpVal;
+
+	/* Last write oprtation on this sync */
+	IMG_UINT64					ui64LastWrite;
+
+} PVRSRV_SYNC_DATA;
+
+/*
+	Client Sync Info structure
+*/
+typedef struct _PVRSRV_CLIENT_SYNC_INFO_
+{
+	/* mapping of the kernel sync data */
+	PVRSRV_SYNC_DATA		*psSyncData;
+
+	/* Device accessible WriteOp Info */
+	IMG_DEV_VIRTADDR		sWriteOpsCompleteDevVAddr;
+
+	/* Device accessible ReadOp Info */
+	IMG_DEV_VIRTADDR		sReadOpsCompleteDevVAddr;
+
+	/* Device accessible ReadOp2 Info */
+	IMG_DEV_VIRTADDR		sReadOps2CompleteDevVAddr;
+
+	/* handle to client mapping data (OS specific) */
+	IMG_HANDLE					hMappingInfo;
+
+	/* handle to kernel sync info */
+	IMG_HANDLE					hKernelSyncInfo;
+
+} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+
+/*!
+ *****************************************************************************
+ * Resource locking structure
+ *****************************************************************************/
+typedef struct PVRSRV_RESOURCE_TAG
+{
+	volatile IMG_UINT32 ui32Lock;
+	IMG_UINT32 			ui32ID;
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	IMG_VOID			*pOSSyncPrimitive;
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+}PVRSRV_RESOURCE;
+typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+
+
+/* command complete callback pfn prototype */
+typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
+typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+
+/* private command handler prototype */
+typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+
+
+/*
+	rectangle structure required by Lock API
+*/
+typedef struct _IMG_RECT_
+{
+	IMG_INT32	x0;
+	IMG_INT32	y0;
+	IMG_INT32	x1;
+	IMG_INT32	y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+	IMG_INT16	x0;
+	IMG_INT16	y0;
+	IMG_INT16	x1;
+	IMG_INT16	y1;
+}IMG_RECT_16;
+
+
+/* common pfn between BC/DC */
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
+											IMG_HANDLE,
+											IMG_SYS_PHYADDR**,
+											IMG_UINT32*,
+											IMG_VOID**,
+											IMG_HANDLE*,
+											IMG_BOOL*,
+											IMG_UINT32*);
+
+
+/*
+	Display dimension structure definition
+*/
+typedef struct DISPLAY_DIMS_TAG
+{
+	IMG_UINT32	ui32ByteStride;
+	IMG_UINT32	ui32Width;
+	IMG_UINT32	ui32Height;
+} DISPLAY_DIMS;
+
+
+/*
+	Display format structure definition
+*/
+typedef struct DISPLAY_FORMAT_TAG
+{
+	/* pixel format type */
+	PVRSRV_PIXEL_FORMAT		pixelformat;
+} DISPLAY_FORMAT;
+
+/*
+	Display Surface Attributes structure definition
+*/
+typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
+{
+	/* pixel format type */
+	PVRSRV_PIXEL_FORMAT		pixelformat;
+	/* dimensions information structure array */
+	DISPLAY_DIMS			sDims;
+} DISPLAY_SURF_ATTRIBUTES;
+
+
+/*
+	Display Mode information structure definition
+*/
+typedef struct DISPLAY_MODE_INFO_TAG
+{
+	/* pixel format type */
+	PVRSRV_PIXEL_FORMAT		pixelformat;
+	/* dimensions information structure array */
+	DISPLAY_DIMS			sDims;
+	/* refresh rate of the display */
+	IMG_UINT32				ui32RefreshHZ;
+	/* OEM specific flags */
+	IMG_UINT32				ui32OEMFlags;
+} DISPLAY_MODE_INFO;
+
+#define MAX_DISPLAY_NAME_SIZE	(64) /* arbitrary choice! */
+
+/*
+	Display info structure definition
+*/
+typedef struct DISPLAY_INFO_TAG
+{
+	/* max swapchains supported */
+	IMG_UINT32 ui32MaxSwapChains;
+	/* max buffers in a swapchain */
+	IMG_UINT32 ui32MaxSwapChainBuffers;
+	/* min swap interval supported */
+	IMG_UINT32 ui32MinSwapInterval;
+	/* max swap interval supported */
+	IMG_UINT32 ui32MaxSwapInterval;
+	/* physical dimensions of the display required for DPI calc. */
+	IMG_UINT32 ui32PhysicalWidthmm;
+	IMG_UINT32 ui32PhysicalHeightmm;
+	/* display name */
+	IMG_CHAR	szDisplayName[MAX_DISPLAY_NAME_SIZE];
+#if defined(SUPPORT_HW_CURSOR)
+	/* cursor dimensions */
+	IMG_UINT16	ui32CursorWidth;
+	IMG_UINT16	ui32CursorHeight;
+#endif
+} DISPLAY_INFO;
+
+typedef struct ACCESS_INFO_TAG
+{
+	IMG_UINT32		ui32Size;
+	IMG_UINT32  	ui32FBPhysBaseAddress;
+	IMG_UINT32		ui32FBMemAvailable;			/* size of usable FB memory */
+	IMG_UINT32  	ui32SysPhysBaseAddress;
+	IMG_UINT32		ui32SysSize;
+	IMG_UINT32		ui32DevIRQ;
+}ACCESS_INFO;
+
+
+
+#if defined(PDUMP_SUSPEND_IS_PER_THREAD)
+/** Present only on WinMobile 6.5 */
+
+typedef struct {
+	IMG_UINT32 threadId;
+	IMG_INT    suspendCount;
+} PVRSRV_THREAD_SUSPEND_COUNT;
+
+#define PVRSRV_PDUMP_SUSPEND_Q_NAME "PVRSRVPDumpSuspendMsgQ"
+#define PVRSRV_PDUMP_SUSPEND_Q_LENGTH 8
+
+#endif /* defined(PDUMP_SUSPEND_IS_PER_THREAD) */
+
+
+/*!
+ *****************************************************************************
+ * This structure is used for OS independent registry (profile) access
+ *****************************************************************************/
+typedef struct _PVRSRV_REGISTRY_INFO_
+{
+    IMG_UINT32		ui32DevCookie;
+    IMG_PCHAR		pszKey;
+    IMG_PCHAR		pszValue;
+    IMG_PCHAR		pszBuf;
+    IMG_UINT32		ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReadRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWriteRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+
+#define PVRSRV_BC_FLAGS_YUVCSC_RANGE_MASK		(0x01)
+#define PVRSRV_BC_FLAGS_YUVCSC_RANGE_SHIFT		(0x00)
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE	(0 << PVRSRV_BC_FLAGS_YUVCSC_RANGE_SHIFT)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE		(1 << PVRSRV_BC_FLAGS_YUVCSC_RANGE_SHIFT)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CS_MASK			(0x02)
+#define PVRSRV_BC_FLAGS_YUVCSC_CS_SHIFT			(0x01)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601			(0 << PVRSRV_BC_FLAGS_YUVCSC_CS_SHIFT)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709			(1 << PVRSRV_BC_FLAGS_YUVCSC_CS_SHIFT)
+
+#define PVRSRV_BC_FLAGS_RGB_RANGE_MASK			(0x04)
+#define PVRSRV_BC_FLAGS_RGB_RANGE_SHIFT			(0x02)
+#define PVRSRV_BC_FLAGS_RGB_FULL_RANGE			(0 << PVRSRV_BC_FLAGS_RGB_RANGE_SHIFT)
+#define PVRSRV_BC_FLAGS_RGB_CONFORMANT_RANGE	(1 << PVRSRV_BC_FLAGS_RGB_RANGE_SHIFT)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_MASK				(PVRSRV_BC_FLAGS_YUVCSC_RANGE_MASK | PVRSRV_BC_FLAGS_YUVCSC_CS_MASK | PVRSRV_BC_FLAGS_RGB_RANGE_MASK)
+
+
+#define MAX_BUFFER_DEVICE_NAME_SIZE	(50) /* arbitrary choice! */
+
+/* buffer information structure */
+typedef struct BUFFER_INFO_TAG
+{
+	IMG_UINT32 			ui32BufferCount;
+	IMG_UINT32			ui32BufferDeviceID;
+	PVRSRV_PIXEL_FORMAT	pixelformat;
+	IMG_UINT32			ui32ByteStride;
+	IMG_UINT32			ui32Width;
+	IMG_UINT32			ui32Height;
+	IMG_UINT32			ui32Flags;
+	IMG_CHAR			szDeviceName[MAX_BUFFER_DEVICE_NAME_SIZE];
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_
+{
+	WEAVE=0x0,
+	BOB_ODD,
+	BOB_EVEN,
+	BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif /* __SERVICESEXT_H__ */
+/*****************************************************************************
+ End of file (servicesext.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/include4/sgx_options.h b/drivers/gpu/pvr/include4/sgx_options.h
new file mode 100644
index 0000000..230e8ad
--- /dev/null
+++ b/drivers/gpu/pvr/include4/sgx_options.h
@@ -0,0 +1,245 @@
+/*************************************************************************/ /*!
+@Title          
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* Each build option listed here is packed into a dword which
+ * provides up to 32 flags (or up to 28 flags plus a numeric
+ * value in the range 0-15 which corresponds to the number of
+ * cores minus one if SGX_FEATURE_MP is defined). The corresponding
+ * bit is set if the build option was enabled at compile time.
+ *
+ * In order to extract the enabled build flags the INTERNAL_TEST
+ * switch should be enabled in a client program which includes this
+ * header. Then the client can test specific build flags by reading
+ * the bit value at ##OPTIONNAME##_SET_OFFSET in SGX_BUILD_OPTIONS.
+ *
+ * IMPORTANT: add new options to unused bits or define a new dword
+ * (e.g. SGX_BUILD_OPTIONS2) so that the bitfield remains backwards
+ * compatible.
+ */
+
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+#define DEBUG_SET_OFFSET	OPTIONS_BIT0
+#define OPTIONS_BIT0		0x1U
+#else
+#define OPTIONS_BIT0		0x0
+#endif /* DEBUG */
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+#define PDUMP_SET_OFFSET	OPTIONS_BIT1
+#define OPTIONS_BIT1		(0x1U << 1)
+#else
+#define OPTIONS_BIT1		0x0
+#endif /* PDUMP */
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined (INTERNAL_TEST)
+#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET		OPTIONS_BIT2
+#define OPTIONS_BIT2		(0x1U << 2)
+#else
+#define OPTIONS_BIT2		0x0
+#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
+
+#if defined(SUPPORT_HW_RECOVERY) || defined (INTERNAL_TEST)
+#define SUPPORT_HW_RECOVERY_SET_OFFSET	OPTIONS_BIT3
+#define OPTIONS_BIT3		(0x1U << 3)
+#else
+#define OPTIONS_BIT3		0x0
+#endif /* SUPPORT_HW_RECOVERY */
+
+
+
+#if defined(PVR_SECURE_HANDLES) || defined (INTERNAL_TEST)
+#define PVR_SECURE_HANDLES_SET_OFFSET	OPTIONS_BIT4
+#define OPTIONS_BIT4		(0x1U << 4)
+#else
+#define OPTIONS_BIT4		0x0
+#endif /* PVR_SECURE_HANDLES */
+
+#if defined(SGX_BYPASS_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_BYPASS_SYSTEM_CACHE_SET_OFFSET	OPTIONS_BIT5
+#define OPTIONS_BIT5		(0x1U << 5)
+#else
+#define OPTIONS_BIT5		0x0
+#endif /* SGX_BYPASS_SYSTEM_CACHE */
+
+#if defined(SGX_DMS_AGE_ENABLE) || defined (INTERNAL_TEST)
+#define SGX_DMS_AGE_ENABLE_SET_OFFSET	OPTIONS_BIT6
+#define OPTIONS_BIT6		(0x1U << 6)
+#else
+#define OPTIONS_BIT6		0x0
+#endif /* SGX_DMS_AGE_ENABLE */
+
+#if defined(SGX_FAST_DPM_INIT) || defined (INTERNAL_TEST)
+#define SGX_FAST_DPM_INIT_SET_OFFSET	OPTIONS_BIT8
+#define OPTIONS_BIT8		(0x1U << 8)
+#else
+#define OPTIONS_BIT8		0x0
+#endif /* SGX_FAST_DPM_INIT */
+
+#if defined(SGX_FEATURE_WRITEBACK_DCU) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_DCU_SET_OFFSET	OPTIONS_BIT9
+#define OPTIONS_BIT9		(0x1U << 9)
+#else
+#define OPTIONS_BIT9		0x0
+#endif /* SGX_FEATURE_WRITEBACK_DCU */
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MP_SET_OFFSET	OPTIONS_BIT10
+#define OPTIONS_BIT10		(0x1U << 10)
+#else
+#define OPTIONS_BIT10		0x0
+#endif /* SGX_FEATURE_MP */
+
+#define OPTIONS_BIT11		0x0
+
+#define OPTIONS_BIT12		0x0
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_SYSTEM_CACHE_SET_OFFSET	OPTIONS_BIT13
+#define OPTIONS_BIT13		(0x1U << 13)
+#else
+#define OPTIONS_BIT13		0x0
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+#if defined(SGX_SUPPORT_HWPROFILING) || defined (INTERNAL_TEST)
+#define SGX_SUPPORT_HWPROFILING_SET_OFFSET	OPTIONS_BIT14
+#define OPTIONS_BIT14		(0x1U << 14)
+#else
+#define OPTIONS_BIT14		0x0
+#endif /* SGX_SUPPORT_HWPROFILING */
+
+
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) || defined (INTERNAL_TEST)
+#define SUPPORT_ACTIVE_POWER_MANAGEMENT_SET_OFFSET	OPTIONS_BIT15
+#define OPTIONS_BIT15		(0x1U << 15)
+#else
+#define OPTIONS_BIT15		0x0
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+#if defined(SUPPORT_DISPLAYCONTROLLER_TILING) || defined (INTERNAL_TEST)
+#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET	OPTIONS_BIT16
+#define OPTIONS_BIT16		(0x1U << 16)
+#else
+#define OPTIONS_BIT16		0x0
+#endif /* SUPPORT_DISPLAYCONTROLLER_TILING */
+
+#if defined(SUPPORT_PERCONTEXT_PB) || defined (INTERNAL_TEST)
+#define SUPPORT_PERCONTEXT_PB_SET_OFFSET	OPTIONS_BIT17
+#define OPTIONS_BIT17		(0x1U << 17)
+#else
+#define OPTIONS_BIT17		0x0
+#endif /* SUPPORT_PERCONTEXT_PB */
+
+#if defined(SUPPORT_SGX_HWPERF) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_HWPERF_SET_OFFSET	OPTIONS_BIT18
+#define OPTIONS_BIT18		(0x1U << 18)
+#else
+#define OPTIONS_BIT18		0x0
+#endif /* SUPPORT_SGX_HWPERF */
+
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_MMU_DUMMY_PAGE_SET_OFFSET	OPTIONS_BIT19
+#define OPTIONS_BIT19		(0x1U << 19)
+#else
+#define OPTIONS_BIT19		0x0
+#endif /* SUPPORT_SGX_MMU_DUMMY_PAGE */
+
+#if defined(SUPPORT_SGX_PRIORITY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET	OPTIONS_BIT20
+#define OPTIONS_BIT20		(0x1U << 20)
+#else
+#define OPTIONS_BIT20		0x0
+#endif /* SUPPORT_SGX_PRIORITY_SCHEDULING */
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING_SET_OFFSET	OPTIONS_BIT21
+#define OPTIONS_BIT21		(0x1U << 21)
+#else
+#define OPTIONS_BIT21		0x0
+#endif /* SUPPORT_SGX_LOW_LATENCY_SCHEDULING */
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#if defined(SGX_FEATURE_MP_CORE_COUNT)
+#define OPTIONS_HIGHBYTE ((SGX_FEATURE_MP_CORE_COUNT-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET)
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET	28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK		0xFF
+#else
+#define OPTIONS_HIGHBYTE (((SGX_FEATURE_MP_CORE_COUNT_TA-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET) |\
+		((SGX_FEATURE_MP_CORE_COUNT_3D-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET_3D))
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET	24UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET_3D	28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK		0xFF
+#endif
+#else /* SGX_FEATURE_MP */
+#define OPTIONS_HIGHBYTE	0x0
+#endif /* SGX_FEATURE_MP */
+
+
+
+#define SGX_BUILD_OPTIONS	\
+	OPTIONS_BIT0 |\
+	OPTIONS_BIT1 |\
+	OPTIONS_BIT2 |\
+	OPTIONS_BIT3 |\
+	OPTIONS_BIT4 |\
+	OPTIONS_BIT5 |\
+	OPTIONS_BIT6 |\
+	OPTIONS_BIT8 |\
+	OPTIONS_BIT9 |\
+	OPTIONS_BIT10 |\
+	OPTIONS_BIT11 |\
+	OPTIONS_BIT12 |\
+	OPTIONS_BIT13 |\
+	OPTIONS_BIT14 |\
+	OPTIONS_BIT15 |\
+	OPTIONS_BIT16 |\
+	OPTIONS_BIT17 |\
+	OPTIONS_BIT18 |\
+	OPTIONS_BIT19 |\
+	OPTIONS_BIT20 |\
+	OPTIONS_BIT21 |\
+	OPTIONS_HIGHBYTE
+
diff --git a/drivers/gpu/pvr/include4/sgxapi_km.h b/drivers/gpu/pvr/include4/sgxapi_km.h
new file mode 100644
index 0000000..1b9fd65
--- /dev/null
+++ b/drivers/gpu/pvr/include4/sgxapi_km.h
@@ -0,0 +1,554 @@
+/*************************************************************************/ /*!
+@Title          SGX KM API Header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Exported SGX API details
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __SGXAPI_KM_H__
+#define __SGXAPI_KM_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "sgxdefs.h"
+
+#if (defined(__linux__) || defined(__QNXNTO__)) && !defined(USE_CODE)
+	#if defined(__KERNEL__)
+		#include <asm/unistd.h>
+	#else
+		#include <unistd.h>
+	#endif
+#endif
+
+/******************************************************************************
+ Some defines...
+******************************************************************************/
+
+/* SGX Heap IDs, note: not all heaps are available to clients */
+#define SGX_UNDEFINED_HEAP_ID					(~0LU)
+#define SGX_GENERAL_HEAP_ID						0
+#define SGX_TADATA_HEAP_ID						1
+#define SGX_KERNEL_CODE_HEAP_ID					2
+#define SGX_KERNEL_DATA_HEAP_ID					3
+#define SGX_PIXELSHADER_HEAP_ID					4
+#define SGX_VERTEXSHADER_HEAP_ID				5
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID			6
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID			7
+#define SGX_SYNCINFO_HEAP_ID					8
+#define SGX_SHARED_3DPARAMETERS_HEAP_ID				9
+#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID			10
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+#define SGX_GENERAL_MAPPING_HEAP_ID				11
+#endif
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_2D_HEAP_ID							12
+#endif
+#if defined(SUPPORT_MEMORY_TILING)
+#define SGX_VPB_TILED_HEAP_ID			14
+#endif
+
+#if defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION)
+		#define SGX_TEXTURE_HEAP_ID                     15      
+		#define SGX_MAX_HEAP_ID                         16      
+#else
+		#define SGX_MAX_HEAP_ID 						15
+#endif
+
+/*
+ * Keep SGX_3DPARAMETERS_HEAP_ID as TQ full custom
+ * shaders need it to select which heap to write
+ * their ISP controll stream to.
+ */
+#if (defined(SUPPORT_PERCONTEXT_PB) || defined(SUPPORT_HYBRID_PB))
+#define SGX_3DPARAMETERS_HEAP_ID			SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID	
+#else
+#define SGX_3DPARAMETERS_HEAP_ID			SGX_SHARED_3DPARAMETERS_HEAP_ID
+#endif
+/* Define for number of bytes between consecutive code base registers */
+#if defined(SGX543) || defined(SGX544) || defined(SGX554)
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS		23
+#else
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS		19
+#endif
+
+#define SGX_MAX_TA_STATUS_VALS	32
+#define SGX_MAX_3D_STATUS_VALS	4
+
+/* sync info structure array size */
+#define SGX_MAX_SRC_SYNCS_TA				32
+#define SGX_MAX_DST_SYNCS_TA				1
+/* note: only one dst sync is supported by the 2D paths */
+#define SGX_MAX_SRC_SYNCS_TQ				6
+#define SGX_MAX_DST_SYNCS_TQ				2
+
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+#define	PVRSRV_SGX_HWPERF_NUM_COUNTERS	8
+#define	PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS 11
+#else
+#define	PVRSRV_SGX_HWPERF_NUM_COUNTERS	9
+#define	PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS 8
+#endif /* SGX543 */
+
+#define PVRSRV_SGX_HWPERF_INVALID					0x1
+
+#define PVRSRV_SGX_HWPERF_TRANSFER					0x2
+#define PVRSRV_SGX_HWPERF_TA						0x3
+#define PVRSRV_SGX_HWPERF_3D						0x4
+#define PVRSRV_SGX_HWPERF_2D						0x5
+#define PVRSRV_SGX_HWPERF_POWER						0x6
+#define PVRSRV_SGX_HWPERF_PERIODIC					0x7
+#define PVRSRV_SGX_HWPERF_3DSPM						0x8
+#define PVRSRV_SGX_HWPERF_TA_OCL					0x9
+#define PVRSRV_SGX_HWPERF_3D_OCL					0xA
+#define PVRSRV_SGX_HWPERF_3DSPM_OCL					0xB
+
+#define PVRSRV_SGX_HWPERF_MK_EVENT					0x101
+#define PVRSRV_SGX_HWPERF_MK_TA						0x102
+#define PVRSRV_SGX_HWPERF_MK_3D						0x103
+#define PVRSRV_SGX_HWPERF_MK_2D						0x104
+#define PVRSRV_SGX_HWPERF_MK_TRANSFER_DUMMY				0x105
+#define PVRSRV_SGX_HWPERF_MK_TA_DUMMY					0x106
+#define PVRSRV_SGX_HWPERF_MK_3D_DUMMY					0x107
+#define PVRSRV_SGX_HWPERF_MK_2D_DUMMY					0x108
+#define PVRSRV_SGX_HWPERF_MK_TA_LOCKUP					0x109
+#define PVRSRV_SGX_HWPERF_MK_3D_LOCKUP					0x10A
+#define PVRSRV_SGX_HWPERF_MK_2D_LOCKUP					0x10B
+#define PVRSRV_SGX_HWPERF_MK_HK						0x10C
+
+#define PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT			28
+#define PVRSRV_SGX_HWPERF_TYPE_OP_MASK				((1UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT) - 1)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_START				(0UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_END				(1Ul << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_START		(PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_END			(PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_START				(PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_END				(PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_START				(PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_END				(PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_START				(PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_END				(PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_START			(PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_END			(PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_PERIODIC				(PVRSRV_SGX_HWPERF_PERIODIC)
+#define PVRSRV_SGX_HWPERF_TYPE_3DSPM_START			(PVRSRV_SGX_HWPERF_3DSPM | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3DSPM_END			(PVRSRV_SGX_HWPERF_3DSPM | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3DSPM_OCL_START			(PVRSRV_SGX_HWPERF_3DSPM_OCL | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3DSPM_OCL_END			(PVRSRV_SGX_HWPERF_3DSPM_OCL | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_OCL_START			(PVRSRV_SGX_HWPERF_TA_OCL | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_OCL_END			(PVRSRV_SGX_HWPERF_TA_OCL | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_OCL_START			(PVRSRV_SGX_HWPERF_3D_OCL | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_OCL_END			(PVRSRV_SGX_HWPERF_3D_OCL | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TRANSFER_DUMMY_START		(PVRSRV_SGX_HWPERF_MK_TRANSFER_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TRANSFER_DUMMY_END		(PVRSRV_SGX_HWPERF_MK_TRANSFER_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_DUMMY_START		(PVRSRV_SGX_HWPERF_MK_TA_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_DUMMY_END			(PVRSRV_SGX_HWPERF_MK_TA_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_DUMMY_START		(PVRSRV_SGX_HWPERF_MK_3D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_DUMMY_END			(PVRSRV_SGX_HWPERF_MK_3D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_DUMMY_START		(PVRSRV_SGX_HWPERF_MK_2D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_DUMMY_END			(PVRSRV_SGX_HWPERF_MK_2D_DUMMY | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_LOCKUP			(PVRSRV_SGX_HWPERF_MK_TA_LOCKUP)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_LOCKUP			(PVRSRV_SGX_HWPERF_MK_3D_LOCKUP)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_LOCKUP			(PVRSRV_SGX_HWPERF_MK_2D_LOCKUP)
+
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_START		(PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_END			(PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_START			(PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_END			(PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_START			(PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_END			(PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_START			(PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_END			(PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_HK_START			(PVRSRV_SGX_HWPERF_MK_HK | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_HK_END			(PVRSRV_SGX_HWPERF_MK_HK | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+
+#define PVRSRV_SGX_HWPERF_STATUS_OFF				(0x0)
+#define PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS		(1UL << 0)
+#define PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON		(1UL << 1)
+#define PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON		(1UL << 2)
+#define PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON	(1UL << 3)
+
+
+/*!
+ *****************************************************************************
+ * One entry in the HWPerf Circular Buffer. 
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_HWPERF_CB_ENTRY_
+{
+	IMG_UINT32	ui32FrameNo;
+	IMG_UINT32	ui32PID;
+	IMG_UINT32	ui32RTData;
+	IMG_UINT32	ui32Type;
+	IMG_UINT32	ui32Ordinal;
+	IMG_UINT32	ui32Info;
+	IMG_UINT32	ui32Clocksx16;
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	IMG_UINT32	ui32SystraceIndex;
+#endif
+	/* NOTE: There should always be at least as many 3D cores as TA cores. */	
+	IMG_UINT32	ui32Counters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+	IMG_UINT32	ui32MiscCounters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS];
+} PVRSRV_SGX_HWPERF_CB_ENTRY;
+
+
+/*
+	Status values control structure
+*/
+typedef struct _CTL_STATUS_
+{
+	IMG_DEV_VIRTADDR	sStatusDevAddr;
+	IMG_UINT32			ui32StatusValue;
+} CTL_STATUS;
+
+
+/*!
+	List of possible requests/commands to SGXGetMiscInfo()
+*/
+typedef enum _SGX_MISC_INFO_REQUEST_
+{
+	SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+	SGX_MISC_INFO_REQUEST_CLOCKSPEED_SLCSIZE,
+	SGX_MISC_INFO_REQUEST_SGXREV,
+	SGX_MISC_INFO_REQUEST_DRIVER_SGXREV,
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	SGX_MISC_INFO_REQUEST_MEMREAD,
+	SGX_MISC_INFO_REQUEST_MEMCOPY,
+#endif /* SUPPORT_SGX_EDM_MEMORY_DEBUG */
+	SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+	SGX_MISC_INFO_REQUEST_SET_BREAKPOINT,
+	SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT,
+	SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT,
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS */
+	SGX_MISC_INFO_DUMP_DEBUG_INFO,
+	SGX_MISC_INFO_DUMP_DEBUG_INFO_FORCE_REGS,
+	SGX_MISC_INFO_PANIC,
+	SGX_MISC_INFO_REQUEST_SPM,
+	SGX_MISC_INFO_REQUEST_ACTIVEPOWER,
+	SGX_MISC_INFO_REQUEST_LOCKUPS,
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	SGX_MISC_INFO_REQUEST_EDM_STATUS_BUFFER_INFO,
+#endif
+	SGX_MISC_INFO_REQUEST_FORCE_I32 = 0x7fffffff
+} SGX_MISC_INFO_REQUEST;
+
+
+/******************************************************************************
+ * Struct for passing SGX core rev/features from ukernel to driver.
+ * This is accessed from the kernel part of the driver and microkernel; it is
+ * only accessed in user space during buffer allocation in srvinit.
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_FEATURES
+{
+	IMG_UINT32			ui32CoreRev;	/*!< SGX Core revision from HW register */
+	IMG_UINT32			ui32CoreID;		/*!< SGX Core ID from HW register */
+	IMG_UINT32			ui32DDKVersion;	/*!< software DDK version */
+	IMG_UINT32			ui32DDKBuild;	/*!< software DDK build no. */
+	IMG_UINT32			ui32CoreIdSW;	/*!< software core version (ID), e.g. SGX535, SGX540 */
+	IMG_UINT32			ui32CoreRevSW;	/*!< software core revision */
+	IMG_UINT32			ui32BuildOptions;	/*!< build options bit-field */
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	IMG_UINT32			ui32DeviceMemValue;		/*!< device mem value read from ukernel */
+#elif defined(USE_64BIT_COMPAT)
+	IMG_UINT32			ui32Padding;
+#endif
+} PVRSRV_SGX_MISCINFO_FEATURES;
+
+typedef struct _PVRSRV_SGX_MISCINFO_QUERY_CLOCKSPEED_SLCSIZE
+{
+	IMG_UINT32                      ui32SGXClockSpeed;
+	IMG_UINT32                      ui32SGXSLCSize;
+} PVRSRV_SGX_MISCINFO_QUERY_CLOCKSPEED_SLCSIZE;
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+/******************************************************************************
+ * Struct for getting access to the EDM Status Buffer
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_EDM_STATUS_BUFFER_INFO
+{
+	IMG_DEV_VIRTADDR	sDevVAEDMStatusBuffer;	/*!< DevVAddr of the EDM status buffer */
+	IMG_HANDLE		pvEDMStatusBuffer;		/*!< CPUVAddr of the EDM status buffer */
+} PVRSRV_SGX_MISCINFO_EDM_STATUS_BUFFER_INFO;
+#endif
+
+
+/******************************************************************************
+ * Struct for getting lock-up stats from the kernel driver
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_LOCKUPS
+{
+	IMG_UINT32			ui32HostDetectedLockups; /*!< Host timer detected lockups */
+	IMG_UINT32			ui32uKernelDetectedLockups; /*!< Microkernel detected lockups */
+} PVRSRV_SGX_MISCINFO_LOCKUPS;
+
+
+/******************************************************************************
+ * Struct for getting lock-up stats from the kernel driver
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_ACTIVEPOWER
+{
+	IMG_UINT32			ui32NumActivePowerEvents; /*!< active power events */
+#if defined(USE_64BIT_COMPAT)
+	IMG_UINT32			ui32Padding;
+#endif
+} PVRSRV_SGX_MISCINFO_ACTIVEPOWER;
+
+
+/******************************************************************************
+ * Struct for getting SPM stats fro the kernel driver
+ ******************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_SPM
+{
+	IMG_HANDLE			hRTDataSet;				/*!< render target data set handle returned from SGXAddRenderTarget */
+	IMG_UINT32			ui32NumOutOfMemSignals; /*!< Number of Out of Mem Signals */
+	IMG_UINT32			ui32NumSPMRenders;	/*!< Number of SPM renders */
+} PVRSRV_SGX_MISCINFO_SPM;
+
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+/*!
+ ******************************************************************************
+ * Structure for SGX break points control
+ *****************************************************************************/
+typedef struct _SGX_BREAKPOINT_INFO
+{
+	/* set/clear BP boolean */
+	IMG_BOOL					bBPEnable;
+	/* Index of BP to set */
+	IMG_UINT32					ui32BPIndex;
+	/* On which DataMaster(s) should the breakpoint fire? */
+	IMG_UINT32                  ui32DataMasterMask;
+	/* DevVAddr of BP to set */
+	IMG_DEV_VIRTADDR			sBPDevVAddr, sBPDevVAddrEnd;
+	/* Whether or not the desired breakpoint will be trapped */
+	IMG_BOOL                    bTrapped;
+	/* Will the requested breakpoint fire for reads? */
+	IMG_BOOL                    bRead;
+	/* Will the requested breakpoint fire for writes? */
+	IMG_BOOL                    bWrite;
+	/* Has a breakpoint been trapped? */
+	IMG_BOOL                    bTrappedBP;
+	/* Extra information recorded about a trapped breakpoint */
+	IMG_UINT32                  ui32CoreNum;
+	IMG_DEV_VIRTADDR            sTrappedBPDevVAddr;
+	IMG_UINT32                  ui32TrappedBPBurstLength;
+	IMG_BOOL                    bTrappedBPRead;
+	IMG_UINT32                  ui32TrappedBPDataMaster;
+	IMG_UINT32                  ui32TrappedBPTag;
+} SGX_BREAKPOINT_INFO;
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS */
+
+
+/*!
+ ******************************************************************************
+ * Structure for setting the hardware performance status
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS
+{
+	/* See PVRSRV_SGX_HWPERF_STATUS_* */
+	IMG_UINT32	ui32NewHWPerfStatus;
+	
+	#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+	/* Specifies the HW's active group selectors */
+	IMG_UINT32	aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+	/* Specifies the HW's active bit selectors */
+	IMG_UINT32	aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+	/* Specifies the HW's counter bit selectors */
+	IMG_UINT32	ui32PerfCounterBitSelect;
+	/* Specifies the HW's sum_mux selectors */
+	IMG_UINT32	ui32PerfSumMux;
+	#else
+	/* Specifies the HW's active group */
+	IMG_UINT32	ui32PerfGroup;
+	#endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
+} PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS;
+
+
+/*!
+ ******************************************************************************
+ * Structure for misc SGX commands in services
+ *****************************************************************************/
+typedef struct _SGX_MISC_INFO_
+{
+	SGX_MISC_INFO_REQUEST	eRequest;	/*!< Command request to SGXGetMiscInfo() */
+#if defined(USE_64BIT_COMPAT)
+	IMG_UINT32				ui32Padding;
+#endif
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	IMG_DEV_VIRTADDR			sDevVAddrSrc;		/*!< dev virtual addr for mem read */
+	IMG_DEV_VIRTADDR			sDevVAddrDest;		/*!< dev virtual addr for mem write */
+	IMG_HANDLE					hDevMemContext;		/*!< device memory context for mem debug */
+#endif
+	union
+	{
+		IMG_UINT32	reserved;	/*!< Unused: ensures valid code in the case everything else is compiled out */
+		PVRSRV_SGX_MISCINFO_FEATURES						sSGXFeatures;
+		IMG_UINT32											ui32SGXClockSpeed;
+		PVRSRV_SGX_MISCINFO_QUERY_CLOCKSPEED_SLCSIZE				sQueryClockSpeedSLCSize;
+		PVRSRV_SGX_MISCINFO_ACTIVEPOWER						sActivePower;
+		PVRSRV_SGX_MISCINFO_LOCKUPS							sLockups;
+		PVRSRV_SGX_MISCINFO_SPM								sSPM;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+		SGX_BREAKPOINT_INFO									sSGXBreakpointInfo;
+#endif
+		PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS				sSetHWPerfStatus;
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+		PVRSRV_SGX_MISCINFO_EDM_STATUS_BUFFER_INFO			sEDMStatusBufferInfo;
+#endif
+	} uData;
+} SGX_MISC_INFO;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+/*
+ * The largest number of source sync objects that can be associated with a blit
+ * command.  Allows for src, pattern, and mask
+ */
+#define PVRSRV_MAX_BLT_SRC_SYNCS		3
+#endif
+
+
+#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH		256
+
+/*
+	Structure for dumping bitmaps
+*/
+typedef struct _SGX_KICKTA_DUMPBITMAP_
+{
+	IMG_DEV_VIRTADDR	sDevBaseAddr;
+	IMG_UINT32			ui32Flags;
+	IMG_UINT32			ui32Width;
+	IMG_UINT32			ui32Height;
+	IMG_UINT32			ui32Stride;
+	IMG_UINT32			ui32PDUMPFormat;
+	IMG_UINT32			ui32BytesPP;
+	IMG_CHAR			pszName[SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+} SGX_KICKTA_DUMPBITMAP, *PSGX_KICKTA_DUMPBITMAP;
+
+#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE	(16)
+
+/*!
+ ******************************************************************************
+ * Data required only when dumping parameters
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_PDUMP_CONTEXT_
+{
+	/* cache control word for micro kernel cache flush/invalidates */
+	IMG_UINT32						ui32CacheControl;
+
+} PVRSRV_SGX_PDUMP_CONTEXT;
+
+
+typedef struct _SGX_KICKTA_DUMP_ROFF_
+{
+	IMG_HANDLE			hKernelMemInfo;						/*< Buffer handle */
+	IMG_UINT32			uiAllocIndex;						/*< Alloc index for LDDM */
+	IMG_UINT32			ui32Offset;							/*< Byte offset to value to dump */
+	IMG_UINT32			ui32Value;							/*< Actual value to dump */
+	IMG_PCHAR			pszName;							/*< Name of buffer */
+} SGX_KICKTA_DUMP_ROFF, *PSGX_KICKTA_DUMP_ROFF;
+
+typedef struct _SGX_KICKTA_DUMP_BUFFER_
+{
+	IMG_UINT32			ui32SpaceUsed;
+	IMG_UINT32			ui32Start;							/*< Byte offset of start to dump */
+	IMG_UINT32			ui32End;							/*< Byte offset of end of dump (non-inclusive) */
+	IMG_UINT32			ui32BufferSize;						/*< Size of buffer */
+	IMG_UINT32			ui32BackEndLength;					/*< Size of back end portion, if End < Start */
+	IMG_UINT32			uiAllocIndex;
+	IMG_HANDLE			hKernelMemInfo;						/*< MemInfo handle for the circular buffer */
+	IMG_HANDLE			hLinAddr;
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+	IMG_HANDLE			hCtrlKernelMemInfo;					/*< MemInfo handle for the control structure of the
+																circular buffer */
+	IMG_DEV_VIRTADDR	sCtrlDevVAddr;						/*< Device virtual address of the memory in the 
+																control structure to be checked */
+#if defined(USE_64BIT_COMPAT)
+	IMG_UINT32 			ui32Padding;
+#endif
+#endif
+	IMG_HANDLE			hName;							/*< Name of buffer */
+
+#if defined (__QNXNTO__)
+	IMG_UINT32          ui32NameLength;                     /*< Number of characters in buffer name */
+#endif
+} SGX_KICKTA_DUMP_BUFFER, *PSGX_KICKTA_DUMP_BUFFER;
+
+#ifdef PDUMP
+/*
+	PDUMP version of above kick structure
+*/
+typedef struct _SGX_KICKTA_PDUMP_
+{
+	// Bitmaps to dump
+	PSGX_KICKTA_DUMPBITMAP		psPDumpBitmapArray;
+	IMG_UINT32						ui32PDumpBitmapSize;
+
+	// Misc buffers to dump (e.g. TA, PDS etc..)
+	PSGX_KICKTA_DUMP_BUFFER	psBufferArray;
+	IMG_UINT32						ui32BufferArraySize;
+
+	// Roffs to dump
+	PSGX_KICKTA_DUMP_ROFF		psROffArray;
+	IMG_UINT32						ui32ROffArraySize;
+} SGX_KICKTA_PDUMP, *PSGX_KICKTA_PDUMP;
+#endif	/* PDUMP */
+
+#if defined(TRANSFER_QUEUE)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+/* Maximum size of ctrl stream for 2d blit command (in 32 bit words) */
+#define SGX_MAX_2D_BLIT_CMD_SIZE 		26
+#define SGX_MAX_2D_SRC_SYNC_OPS			3
+#endif
+#define SGX_MAX_TRANSFER_STATUS_VALS	2
+#define SGX_MAX_TRANSFER_SYNC_OPS	5
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __SGXAPI_KM_H__ */
+
+/******************************************************************************
+ End of file (sgxapi_km.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/include4/sgxscript.h b/drivers/gpu/pvr/include4/sgxscript.h
new file mode 100644
index 0000000..4d103cb
--- /dev/null
+++ b/drivers/gpu/pvr/include4/sgxscript.h
@@ -0,0 +1,108 @@
+/*************************************************************************/ /*!
+@Title          SGX kernel services structues/functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    SGX initialisation script definitions.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __SGXSCRIPT_H__
+#define __SGXSCRIPT_H__
+
+#include "sgxfeaturedefs.h"
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define	SGX_MAX_INIT_COMMANDS	64
+#define	SGX_MAX_PRINT_COMMANDS	64
+#define	SGX_MAX_DEINIT_COMMANDS	16
+
+typedef	enum _SGX_INIT_OPERATION
+{
+	SGX_INIT_OP_ILLEGAL = 0,
+	SGX_INIT_OP_WRITE_HW_REG,
+	SGX_INIT_OP_READ_HW_REG,
+	SGX_INIT_OP_PRINT_HW_REG,
+#if defined(PDUMP)
+	SGX_INIT_OP_PDUMP_HW_REG,
+#endif
+	SGX_INIT_OP_HALT,
+	SGX_INIT_FORCE_I32 = 0x7FFFFFFF
+} SGX_INIT_OPERATION;
+
+typedef union _SGX_INIT_COMMAND
+{
+	SGX_INIT_OPERATION eOp;
+	struct IMG_COMPAT {
+		SGX_INIT_OPERATION eOp;
+		IMG_UINT32 ui32Offset;
+		IMG_UINT32 ui32Value;
+	} sWriteHWReg;
+	struct IMG_COMPAT {
+		SGX_INIT_OPERATION eOp;
+		IMG_UINT32 ui32Offset;
+		IMG_UINT32 ui32Value;
+	} sReadHWReg;
+#if defined(PDUMP)
+	struct IMG_COMPAT {
+		SGX_INIT_OPERATION eOp;
+		IMG_UINT32 ui32Offset;
+		IMG_UINT32 ui32Value;
+	} sPDumpHWReg;
+#endif
+} SGX_INIT_COMMAND;
+
+typedef struct IMG_COMPAT _SGX_INIT_SCRIPTS_
+{
+	SGX_INIT_COMMAND asInitCommandsPart1[SGX_MAX_INIT_COMMANDS];
+	SGX_INIT_COMMAND asInitCommandsPart2[SGX_MAX_INIT_COMMANDS];
+	SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+#if defined(SGX_FEATURE_MP)
+	SGX_INIT_COMMAND asSGXREGDebugCommandsMaster[SGX_MAX_PRINT_COMMANDS];
+#endif
+	SGX_INIT_COMMAND asSGXREGDebugCommandsSlave[SGX_MAX_PRINT_COMMANDS];
+} SGX_INIT_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __SGXSCRIPT_H__ */
+
+/*****************************************************************************
+ End of file (sgxscript.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/include/env/linux/pvr_drm_shared.h b/drivers/gpu/pvr/services4/include/env/linux/pvr_drm_shared.h
new file mode 100644
index 0000000..4b84f6b
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/env/linux/pvr_drm_shared.h
@@ -0,0 +1,76 @@
+/*************************************************************************/ /*!
+@Title          PowerVR drm driver shared definitions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if !defined(__PVR_DRM_SHARED_H__)
+#define __PVR_DRM_SHARED_H__
+
+#if defined(SUPPORT_DRI_DRM)
+
+typedef struct drm_pvr_unpriv_cmd_tag
+{
+    uint32_t cmd;
+    uint32_t res;
+} drm_pvr_unpriv_cmd;
+
+/* DRM command numbers, relative to DRM_COMMAND_BASE */
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define PVR_DRM_SRVKM_CMD	DRM_PVR_RESERVED1	/* Used for PVR Services ioctls */
+#define	PVR_DRM_DISP_CMD	DRM_PVR_RESERVED2	/* Reserved for display class driver */
+#define	PVR_DRM_BC_CMD		DRM_PVR_RESERVED3	/* Reserved for buffer class driver */
+#define PVR_DRM_IS_MASTER_CMD	DRM_PVR_RESERVED4	/* Are we the DRM master? */
+#define PVR_DRM_UNPRIV_CMD	DRM_PVR_RESERVED5	/* PVR driver unprivileged ioctls */
+#define PVR_DRM_DBGDRV_CMD	DRM_PVR_RESERVED6	/* Debug driver (PDUMP) ioctls */
+#else	/* defined(SUPPORT_DRI_DRM_EXT) */
+#define PVR_DRM_SRVKM_CMD	0	/* Used for PVR Services ioctls */
+#define	PVR_DRM_DISP_CMD	1	/* Reserved for display class driver */
+#define	PVR_DRM_BC_CMD		2	/* Reserved for buffer class driver */
+#define PVR_DRM_IS_MASTER_CMD	3	/* Are we the DRM master? */
+#define PVR_DRM_UNPRIV_CMD	4	/* PVR driver unprivileged ioctls */
+#define PVR_DRM_DBGDRV_CMD	5	/* Debug driver (PDUMP) ioctls */
+#endif	/* defined(SUPPORT_DRI_DRM_EXT) */
+
+/* Subcommands of PVR_DRM_UNPRIV_CMD */
+#define	PVR_DRM_UNPRIV_INIT_SUCCESFUL	0 /* PVR Services init succesful */
+
+#endif
+
+#endif /* defined(__PVR_DRM_SHARED_H__) */
+
+
diff --git a/drivers/gpu/pvr/services4/include/ion_sys_private.h b/drivers/gpu/pvr/services4/include/ion_sys_private.h
new file mode 100644
index 0000000..8b2c467
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/ion_sys_private.h
@@ -0,0 +1,50 @@
+/*************************************************************************/ /*!
+@File           ion_sys_private.h
+@Title          System-specific private data for ion support code
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include SUPPORT_ION_HEADER
+
+typedef struct
+{
+	ion_phys_addr_t uiHeapBase;
+	size_t uiHeapSize;
+	IMG_CPU_PHYADDR sPCIAddrRangeStart;
+} ION_TC_PRIVATE_DATA;
diff --git a/drivers/gpu/pvr/services4/include/kernelbuffer.h b/drivers/gpu/pvr/services4/include/kernelbuffer.h
new file mode 100644
index 0000000..6d8aed5
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/kernelbuffer.h
@@ -0,0 +1,97 @@
+/*************************************************************************/ /*!
+@Title          buffer device class API structures and prototypes
+                for kernel services to kernel 3rd party buffer device driver
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	provides display device class API structures and prototypes
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__KERNELBUFFER_H__)
+#define __KERNELBUFFER_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+	Function table and pointers for SRVKM->BUFFER
+*/
+typedef PVRSRV_ERROR (*PFN_OPEN_BC_DEVICE)(IMG_UINT32, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_BC_DEVICE)(IMG_UINT32, IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_GET_BC_INFO)(IMG_HANDLE, BUFFER_INFO*);
+typedef PVRSRV_ERROR (*PFN_GET_BC_BUFFER)(IMG_HANDLE, IMG_UINT32, PVRSRV_SYNC_DATA*, IMG_HANDLE*);
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG
+{
+	IMG_UINT32							ui32TableSize;
+	PFN_OPEN_BC_DEVICE					pfnOpenBCDevice;
+	PFN_CLOSE_BC_DEVICE					pfnCloseBCDevice;
+	PFN_GET_BC_INFO						pfnGetBCInfo;
+	PFN_GET_BC_BUFFER					pfnGetBCBuffer;
+	PFN_GET_BUFFER_ADDR					pfnGetBufferAddr;
+
+} PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+
+/*
+	Function table and pointers for BUFFER->SRVKM
+*/
+typedef PVRSRV_ERROR (*PFN_BC_REGISTER_BUFFER_DEV)(PVRSRV_BC_SRV2BUFFER_KMJTABLE*, IMG_UINT32*);
+typedef IMG_VOID (*PFN_BC_SCHEDULE_DEVICES)(IMG_VOID);
+typedef PVRSRV_ERROR (*PFN_BC_REMOVE_BUFFER_DEV)(IMG_UINT32);	
+
+typedef struct PVRSRV_BC_BUFFER2SRV_KMJTABLE_TAG
+{
+	IMG_UINT32							ui32TableSize;
+	PFN_BC_REGISTER_BUFFER_DEV			pfnPVRSRVRegisterBCDevice;
+	PFN_BC_SCHEDULE_DEVICES				pfnPVRSRVScheduleDevices;
+	PFN_BC_REMOVE_BUFFER_DEV			pfnPVRSRVRemoveBCDevice;
+
+} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+
+/* function to retrieve kernel services function table from kernel services */
+typedef IMG_BOOL (*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE); 
+
+/* Prototype for platforms that access the JTable via linkage */
+IMG_IMPORT IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif/* #if !defined (__KERNELBUFFER_H__) */
diff --git a/drivers/gpu/pvr/services4/include/kerneldisplay.h b/drivers/gpu/pvr/services4/include/kerneldisplay.h
new file mode 100644
index 0000000..fe6ec15
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/kerneldisplay.h
@@ -0,0 +1,239 @@
+/*************************************************************************/ /*!
+@Title          Display device class API structures and prototypes
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provides display device class API structures and prototypes
+                for kernel services to kernel 3rd party display.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_DC_DEVICE)(IMG_UINT32, IMG_HANDLE*, PVRSRV_SYNC_DATA*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_DC_DEVICE)(IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_FORMATS)(IMG_HANDLE, IMG_UINT32*, DISPLAY_FORMAT*);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_DIMS)(IMG_HANDLE,
+										 DISPLAY_FORMAT*,
+										 IMG_UINT32*,
+										 DISPLAY_DIMS*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_SYSTEMBUFFER)(IMG_HANDLE, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_INFO)(IMG_HANDLE, DISPLAY_INFO*);
+typedef PVRSRV_ERROR (*PFN_CREATE_DC_SWAPCHAIN)(IMG_HANDLE,
+												IMG_UINT32, 
+												DISPLAY_SURF_ATTRIBUTES*, 
+												DISPLAY_SURF_ATTRIBUTES*,
+												IMG_UINT32, 
+												PVRSRV_SYNC_DATA**,
+												IMG_UINT32,
+												IMG_HANDLE*, 
+												IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DESTROY_DC_SWAPCHAIN)(IMG_HANDLE, 
+												 IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_GET_DC_BUFFERS)(IMG_HANDLE,
+										   IMG_HANDLE,
+										   IMG_UINT32*,
+										   IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_BUFFER)(IMG_HANDLE,
+											  IMG_HANDLE,
+											  IMG_UINT32,
+											  IMG_HANDLE,
+											  IMG_UINT32,
+											  IMG_RECT*);
+typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
+typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+
+/*
+	Function table for SRVKM->DISPLAY
+*/
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
+{
+	IMG_UINT32						ui32TableSize;
+	PFN_OPEN_DC_DEVICE				pfnOpenDCDevice;
+	PFN_CLOSE_DC_DEVICE				pfnCloseDCDevice;
+	PFN_ENUM_DC_FORMATS				pfnEnumDCFormats;
+	PFN_ENUM_DC_DIMS				pfnEnumDCDims;
+	PFN_GET_DC_SYSTEMBUFFER			pfnGetDCSystemBuffer;
+	PFN_GET_DC_INFO					pfnGetDCInfo;
+	PFN_GET_BUFFER_ADDR				pfnGetBufferAddr;
+	PFN_CREATE_DC_SWAPCHAIN			pfnCreateDCSwapChain;
+	PFN_DESTROY_DC_SWAPCHAIN		pfnDestroyDCSwapChain;
+	PFN_SET_DC_DSTRECT				pfnSetDCDstRect;
+	PFN_SET_DC_SRCRECT				pfnSetDCSrcRect;
+	PFN_SET_DC_DSTCK				pfnSetDCDstColourKey;
+	PFN_SET_DC_SRCCK				pfnSetDCSrcColourKey;
+	PFN_GET_DC_BUFFERS				pfnGetDCBuffers;
+	PFN_SWAP_TO_DC_BUFFER			pfnSwapToDCBuffer;
+	PFN_SET_DC_STATE				pfnSetDCState;
+
+} PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+/* ISR callback pfn prototype */
+typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+
+/*
+	functions exported by kernel services for use by 3rd party kernel display class device driver
+*/
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DISPLAY_DEV)(PVRSRV_DC_SRV2DISP_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_DISPLAY_DEV)(IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_OEM_FUNCTION)(IMG_UINT32, IMG_VOID*, IMG_UINT32, IMG_VOID*, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_COMMANDPROCLIST)(IMG_UINT32, PPFN_CMD_PROC,IMG_UINT32[][2], IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_COMMANDPROCLIST)(IMG_UINT32, IMG_UINT32);
+typedef IMG_VOID (*PFN_DC_CMD_COMPLETE)(IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_SYS_ISR)(PFN_ISR_HANDLER, IMG_VOID*, IMG_UINT32, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POST_POWER,
+											  PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
+											  IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_* PDC_MEM_INFO;
+
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_VADDR)(PDC_MEM_INFO, IMG_CPU_VIRTADDR *pVAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_CPU_PADDR)(PDC_MEM_INFO, IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr);
+typedef PVRSRV_ERROR (*PFN_DC_MEMINFO_GET_BYTE_SIZE)(PDC_MEM_INFO, IMG_SIZE_T *uByteSize);
+typedef IMG_BOOL (*PFN_DC_MEMINFO_IS_PHYS_CONTIG)(PDC_MEM_INFO);
+
+/*
+	Function table for DISPLAY->SRVKM
+*/
+typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
+{
+	IMG_UINT32						ui32TableSize;
+	PFN_DC_REGISTER_DISPLAY_DEV		pfnPVRSRVRegisterDCDevice;
+	PFN_DC_REMOVE_DISPLAY_DEV		pfnPVRSRVRemoveDCDevice;
+	PFN_DC_OEM_FUNCTION				pfnPVRSRVOEMFunction;
+	PFN_DC_REGISTER_COMMANDPROCLIST	pfnPVRSRVRegisterCmdProcList;
+	PFN_DC_REMOVE_COMMANDPROCLIST	pfnPVRSRVRemoveCmdProcList;
+	PFN_DC_CMD_COMPLETE				pfnPVRSRVCmdComplete;
+	PFN_DC_REGISTER_SYS_ISR			pfnPVRSRVRegisterSystemISRHandler;
+	PFN_DC_REGISTER_POWER			pfnPVRSRVRegisterPowerDevice;
+	PFN_DC_MEMINFO_GET_CPU_VADDR	pfnPVRSRVDCMemInfoGetCpuVAddr;
+	PFN_DC_MEMINFO_GET_CPU_PADDR	pfnPVRSRVDCMemInfoGetCpuPAddr;
+	PFN_DC_MEMINFO_GET_BYTE_SIZE	pfnPVRSRVDCMemInfoGetByteSize;
+	PFN_DC_MEMINFO_IS_PHYS_CONTIG	pfnPVRSRVDCMemInfoIsPhysContig;
+
+} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
+{
+	/* Ext Device Handle */
+	IMG_HANDLE hExtDevice;
+
+	/* Ext SwapChain Handle */
+	IMG_HANDLE hExtSwapChain;
+
+	/* number of vsync intervals between successive flips */
+	IMG_UINT32	ui32SwapInterval;
+	
+	/* Ext Buffer Handle (Buffer to Flip to) */
+	IMG_HANDLE hExtBuffer;
+
+	/* private tag */
+	IMG_HANDLE hPrivateTag;
+
+	/* number of clip rects */
+	IMG_UINT32 ui32ClipRectCount;
+
+	/* clip rects */
+	IMG_RECT *psClipRect;
+
+} DISPLAYCLASS_FLIP_COMMAND;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND2_TAG
+{
+	/* Ext Device Handle */
+	IMG_HANDLE hExtDevice;
+
+	/* Ext SwapChain Handle */
+	IMG_HANDLE hExtSwapChain;
+
+	/* number of vsync intervals between successive flips */
+	IMG_UINT32 ui32SwapInterval;
+
+	/* Unused field, padding for compatibility with above structure */
+	IMG_HANDLE hUnused;
+
+	/* private data from userspace */
+	IMG_PVOID  pvPrivData;
+
+	/* length of private data in bytes */
+	IMG_UINT32 ui32PrivDataLength;
+
+	/* meminfos */
+	PDC_MEM_INFO *ppsMemInfos;
+
+	/* number of meminfos */
+	IMG_UINT32 ui32NumMemInfos;
+
+} DISPLAYCLASS_FLIP_COMMAND2;
+
+/* start command IDs from 0 */
+#define DC_FLIP_COMMAND		0
+
+/* States used in PFN_SET_DC_STATE */
+#define DC_STATE_NO_FLUSH_COMMANDS		0
+#define DC_STATE_FLUSH_COMMANDS			1
+
+/* function to retrieve kernel services function table from kernel services */
+typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+
+/* Prototype for platforms that access the JTable via linkage */
+IMG_IMPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+#endif/* #if !defined (__KERNELDISPLAY_H__) */
+
+/******************************************************************************
+ End of file (kerneldisplay.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/include/pdump.h b/drivers/gpu/pvr/services4/include/pdump.h
new file mode 100644
index 0000000..566a118
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/pdump.h
@@ -0,0 +1,51 @@
+/*************************************************************************/ /*!
+@Title          PDUMP flags definitions.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef _SERVICES_PDUMP_H_
+#define _SERVICES_PDUMP_H_
+
+#define PDUMP_FLAGS_NEVER			0x08000000U
+#define PDUMP_FLAGS_LASTFRAME		0x10000000U
+#define PDUMP_FLAGS_RESETLFBUFFER	0x20000000U
+#define PDUMP_FLAGS_CONTINUOUS		0x40000000U
+#define PDUMP_FLAGS_PERSISTENT		0x80000000U
+
+#endif /* _SERVICES_PDUMP_H_ */
+
diff --git a/drivers/gpu/pvr/services4/include/pvr_bridge.h b/drivers/gpu/pvr/services4/include/pvr_bridge.h
new file mode 100644
index 0000000..bffbd37
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/pvr_bridge.h
@@ -0,0 +1,1696 @@
+/*************************************************************************/ /*!
+@Title          PVR Bridge Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the PVR Bridge code
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+
+/*
+ * Bridge Cmd Ids
+ */
+
+
+#ifdef __linux__
+
+	#include <linux/ioctl.h>
+	/*!< Nov 2006: according to ioctl-number.txt 'g' wasn't in use. */
+	#define PVRSRV_IOC_GID      'g'
+	#define PVRSRV_IO(INDEX)    _IO(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+	#define PVRSRV_IOW(INDEX)   _IOW(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+	#define PVRSRV_IOR(INDEX)   _IOR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+	#define PVRSRV_IOWR(INDEX)  _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+
+#else /* __linux__ */
+
+ #if  defined(__QNXNTO__)
+			#define PVRSRV_IOC_GID      (0x0UL)
+		#else
+	#error Unknown platform: Cannot define ioctls
+		#endif
+
+	#define PVRSRV_IO(INDEX)    (PVRSRV_IOC_GID + (INDEX))
+	#define PVRSRV_IOW(INDEX)   (PVRSRV_IOC_GID + (INDEX))
+	#define PVRSRV_IOR(INDEX)   (PVRSRV_IOC_GID + (INDEX))
+	#define PVRSRV_IOWR(INDEX)  (PVRSRV_IOC_GID + (INDEX))
+
+	#define PVRSRV_BRIDGE_BASE                  PVRSRV_IOC_GID
+#endif /* __linux__ */
+
+
+/*
+ * Note *REMEMBER* to update PVRSRV_BRIDGE_LAST_CMD (below) if you add any new
+ * bridge commands!
+ * The command number of PVRSRV_BRIDGE_UM_KM_COMPAT_CHECK needs to be maintained as 0 across previous ddks, for compatibility check command to execute successfully
+ */
+
+#define PVRSRV_BRIDGE_UMKM_CMD_FIRST			0UL
+#define PVRSRV_BRIDGE_UM_KM_COMPAT_CHECK		PVRSRV_IOWR(0)
+#define PVRSRV_BRIDGE_UMKM_CMD_LAST			(0)
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST			(PVRSRV_BRIDGE_UMKM_CMD_LAST + 1)
+#define PVRSRV_BRIDGE_ENUM_DEVICES				PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)	/*!< enumerate device bridge index */
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)	/*!< acquire device data bridge index */
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)	/*!< release device data bridge index */
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)	/*!< create device addressable memory context */
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)	/*!< destroy device addressable memory context */
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)	/*!< get device memory heap info */
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)	/*!< alloc device memory bridge index */
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)	/*!< free device memory bridge index */
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)	/*!< get free device memory bridge index */
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)	/*!< create Cmd Q bridge index */
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)	/*!< destroy Cmd Q bridge index */
+#define	PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)   /*!< generate mmap data from a memory handle */
+#define PVRSRV_BRIDGE_CONNECT_SERVICES			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)	/*!< services connect bridge index */
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)	/*!< services disconnect bridge index */
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)	/*!< wrap device memory bridge index */
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)	/*!< read the kernel meminfo record */
+#define PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_FREE_DEV_VIRTMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_UNMAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_UNMAP_DEV_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER	PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_RELEASE_MMAP_DATA			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_CHG_DEV_MEM_ATTRIBS		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY_2			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2		PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+28)
+#if defined (SUPPORT_ION)
+#define PVRSRV_BRIDGE_MAP_ION_HANDLE			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+29)
+#define PVRSRV_BRIDGE_UNMAP_ION_HANDLE			PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+30)
+#define PVRSRV_BRIDGE_ION_CMD_LAST			(PVRSRV_BRIDGE_CORE_CMD_FIRST+30)
+#else
+#define PVRSRV_BRIDGE_ION_CMD_LAST			(PVRSRV_BRIDGE_CORE_CMD_FIRST+28)
+#endif
+#if defined (SUPPORT_DMABUF)
+#define	PVRSRV_BRIDGE_DMABUF_CMD_FIRST			(PVRSRV_BRIDGE_ION_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAP_DMABUF			PVRSRV_IOWR(PVRSRV_BRIDGE_DMABUF_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNMAP_DMABUF			PVRSRV_IOWR(PVRSRV_BRIDGE_DMABUF_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_DMABUF_CMD_LAST			(PVRSRV_BRIDGE_DMABUF_CMD_FIRST+1)
+#else
+#define PVRSRV_BRIDGE_DMABUF_CMD_LAST			PVRSRV_BRIDGE_ION_CMD_LAST
+#endif
+#define	PVRSRV_BRIDGE_CORE_CMD_LAST			PVRSRV_BRIDGE_DMABUF_CMD_LAST
+/* SIM */
+#define PVRSRV_BRIDGE_SIM_CMD_FIRST				(PVRSRV_BRIDGE_CORE_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT		PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0)	/*!< RTSIM pseudo ISR */
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS		PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1)	/*!< Register RTSIM process thread */
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS	PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)	/*!< Unregister RTSIM process thread */
+#define PVRSRV_BRIDGE_SIM_CMD_LAST				(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+
+/* User Mapping */
+#define PVRSRV_BRIDGE_MAPPING_CMD_FIRST			(PVRSRV_BRIDGE_SIM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE		PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0)	/*!< map CPU phys to user space */
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE		PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1)	/*!< unmap CPU phys to user space */
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP		PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)	/*!< get user copy of Phys to Lin loopup table */
+#define PVRSRV_BRIDGE_MAPPING_CMD_LAST			(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_STATS_CMD_FIRST			(PVRSRV_BRIDGE_MAPPING_CMD_LAST+1)
+#define	PVRSRV_BRIDGE_GET_FB_STATS				PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)	/*!< Get FB memory stats */
+#define PVRSRV_BRIDGE_STATS_CMD_LAST			(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+
+/* API to retrieve misc. info. from services */
+#define PVRSRV_BRIDGE_MISC_CMD_FIRST			(PVRSRV_BRIDGE_STATS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_MISC_INFO				PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0)	/*!< misc. info. */
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO			PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)	/*!< misc. info. */
+#define PVRSRV_BRIDGE_MISC_CMD_LAST				(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+
+/* Overlay ioctls */
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST			(PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES		PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0)	/*!< 3D Overlay rotate blit init */
+#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES		PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)	/*!< 3D Overlay rotate blit deinit */
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST			(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#else
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST			PVRSRV_BRIDGE_MISC_CMD_LAST
+#endif
+
+/* PDUMP */
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST			(PVRSRV_BRIDGE_OVERLAY_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PDUMP_INIT			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_REG				PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_REGPOL			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_COMMENT			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR		PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)	/*!< pdump command structure */
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ	PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE			PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST			(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#else
+/* Note we are carefull here not to leave a large gap in the ioctl numbers.
+ * (Some ports may use these values to index into an array where large gaps can
+ * waste memory) */
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST			PVRSRV_BRIDGE_OVERLAY_CMD_LAST
+#endif
+
+/* DisplayClass APIs */
+#define PVRSRV_BRIDGE_OEM_CMD_FIRST				(PVRSRV_BRIDGE_PDUMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_OEMJTABLE				PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)	/*!< Get OEM Jtable */
+#define PVRSRV_BRIDGE_OEM_CMD_LAST				(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+
+/* device class enum */
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST		(PVRSRV_BRIDGE_OEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY	PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY	PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_CLASS				PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_LAST			(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+2)
+
+/* display class API */
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST		(PVRSRV_BRIDGE_DEVCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_INFO		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS		PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM	PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST		(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+
+/* buffer class API */
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST		(PVRSRV_BRIDGE_DISPCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE	PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE	PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO		PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER	PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST			(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+
+/* Wrap/Unwrap external memory */
+#define PVRSRV_BRIDGE_WRAP_CMD_FIRST			(PVRSRV_BRIDGE_BUFCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_WRAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY			PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_WRAP_CMD_LAST				(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+
+/* Shared memory */
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST		(PVRSRV_BRIDGE_WRAP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM		PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM		PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MAP_MEMINFO_MEM			PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_UNMAP_MEMINFO_MEM			PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST		(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+
+/* Intialisation Service support */
+#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST			(PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INITSRV_CONNECT			PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_INITSRV_DISCONNECT		PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INITSRV_CMD_LAST			(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+
+/* Event Objects */
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST	(PVRSRV_BRIDGE_INITSRV_CMD_LAST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_WAIT			PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_OPEN			PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE		PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST		(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+
+/* Sync ops */
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST		(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
+#define PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SYNC_OPS_TAKE_TOKEN       PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN   PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA	PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_ALLOC_SYNC_INFO           PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_FREE_SYNC_INFO            PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST			(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+9)
+
+/* For sgx_bridge.h (msvdx_bridge.h should probably use these defines too) */
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD		(PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+
+
+/******************************************************************************
+ * Bridge flags
+ *****************************************************************************/
+#define PVRSRV_KERNEL_MODE_CLIENT				1
+
+/******************************************************************************
+ * Generic bridge structures
+ *****************************************************************************/
+
+/******************************************************************************
+ *	bridge return structure
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_RETURN_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE	hData;
+}PVRSRV_BRIDGE_RETURN;
+
+
+/******************************************************************************
+ *	bridge packaging structure
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_PACKAGE_TAG
+{
+	IMG_UINT32			ui32BridgeID;			/*!< ioctl/drvesc index */
+	IMG_UINT32			ui32Size;			/*!< size of structure */
+	IMG_HANDLE			hParamIn;			/*!< input data buffer */
+	IMG_HANDLE			hParamOut;			/*!< output data buffer */
+	IMG_UINT32			ui32InBufferSize;		/*!< size of input data buffer */
+	IMG_UINT32			ui32OutBufferSize;		/*!< size of output data buffer */
+
+	IMG_HANDLE			hKernelServices;		/*!< kernel servcies handle */
+}PVRSRV_BRIDGE_PACKAGE;
+
+
+/******************************************************************************
+ * Input structures for IOCTL/DRVESC
+ *****************************************************************************/
+
+
+/******************************************************************************
+ *	'bridge in' connect to services
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_CONNECT_SERVICES_TAG
+{
+	IMG_UINT32	ui32Flags;
+} PVRSRV_BRIDGE_IN_CONNECT_SERVICES;
+
+/******************************************************************************
+ *	'bridge in' acquire device info
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO_TAG
+{
+	IMG_UINT32		uiDevIndex;
+	PVRSRV_DEVICE_TYPE	eDeviceType;
+} PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO;
+
+
+/******************************************************************************
+ *	'bridge in' enum class
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_ENUMCLASS_TAG
+{
+	PVRSRV_DEVICE_CLASS eDeviceClass;
+} PVRSRV_BRIDGE_IN_ENUMCLASS;
+
+
+/******************************************************************************
+ *	'bridge in' close display class device
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE_TAG
+{
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE;
+
+
+/******************************************************************************
+ *	'bridge in' enum display class formats
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS_TAG
+{
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS;
+
+
+/******************************************************************************
+ *	'bridge in' get display class sysbuffer
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER_TAG
+{
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER;
+
+
+/******************************************************************************
+ *	'bridge in' display class info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO_TAG
+{
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO;
+
+
+/******************************************************************************
+ *	'bridge in' close buffer class device
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE_TAG
+{
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE;
+
+
+/******************************************************************************
+ *	'bridge in' close buffer class device
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO_TAG
+{
+	IMG_HANDLE			hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO;
+
+/******************************************************************************
+ *	'bridge in' get device memory heap info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE 			hDevMemContext;
+}PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO;
+
+
+/******************************************************************************
+ *	'bridge in' create device memory context
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT_TAG
+{
+	IMG_HANDLE			hDevCookie;
+}PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT;
+
+
+/******************************************************************************
+ *	'bridge in' destroy device memory context
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT_TAG
+{
+	IMG_HANDLE 			hDevCookie;
+	IMG_HANDLE 			hDevMemContext;
+}PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT;
+
+
+/******************************************************************************
+ *	'bridge in' alloc device memory
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM_TAG
+{
+	IMG_HANDLE		hDevCookie;
+	IMG_HANDLE		hDevMemHeap;
+
+	IMG_HANDLE		hPrivData;
+	IMG_UINT32		ui32PrivDataLength;
+	IMG_UINT32		ui32Attribs;
+
+	IMG_SIZE_T		uSize;
+	IMG_SIZE_T		uAlignment;
+
+	IMG_UINT32		ui32ChunkSize;
+	IMG_UINT32		ui32NumVirtChunks;
+	IMG_UINT32		ui32NumPhysChunks;
+	IMG_HANDLE		hMapChunk;
+}PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM;
+
+/******************************************************************************
+ *	'bridge in' free device memory
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG
+{
+	IMG_HANDLE		hDevCookie;
+	IMG_HANDLE		hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_FREEDEVICEMEM;
+
+/******************************************************************************
+ *	'bridge in' export device memory
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM_TAG
+{
+	IMG_HANDLE		hDevCookie;
+	IMG_HANDLE		hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM;
+
+/******************************************************************************
+ *	'bridge in' map ion handle
+ *****************************************************************************/
+#define ION_IMPORT_MAX_FDS 3
+#define ION_IMPORT_MAX_CHUNK_COUNT 3
+typedef struct _PVRSRV_BRIDGE_IN_MAP_ION_HANDLE_
+{
+	IMG_UINT32		ui32NumFDs;
+	IMG_INT32		ai32BufferFDs[ION_IMPORT_MAX_FDS];
+	IMG_UINT32		ui32Attribs;
+	IMG_UINT32		ui32ChunkCount;
+	IMG_SIZE_T		auiOffset[ION_IMPORT_MAX_CHUNK_COUNT];
+	IMG_SIZE_T		auiSize[ION_IMPORT_MAX_CHUNK_COUNT];
+	IMG_HANDLE		hDevCookie;
+	IMG_HANDLE		hDevMemHeap;
+} PVRSRV_BRIDGE_IN_MAP_ION_HANDLE;
+
+/******************************************************************************
+ *	'bridge in' unmap ion handle
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_ION_HANDLE_TAG
+{
+	IMG_HANDLE	hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_ION_HANDLE;
+
+/******************************************************************************
+ *	'bridge in' map dmabuf
+ *****************************************************************************/
+typedef struct _PVRSRV_BRIDGE_IN_MAP_DMABUF_
+{
+	IMG_UINT32			ui32BridgeFlags; /* Must be first member of structure */
+	IMG_INT32			i32FD;
+	IMG_SIZE_T			uiOffset;
+	IMG_SIZE_T			uiSize;
+	IMG_UINT32			ui32Attribs;
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hDevMemHeap;
+} PVRSRV_BRIDGE_IN_MAP_DMABUF;
+
+/******************************************************************************
+ *	'bridge in' unmap dmabuf
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_UNMAP_DMABUF_TAG
+{
+	IMG_UINT32              ui32BridgeFlags; /* Must be first member of structure */
+	IMG_HANDLE		hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_DMABUF;
+
+/******************************************************************************
+ *	'bridge in' get free device memory
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM_TAG
+{
+	IMG_UINT32			ui32Flags;
+} PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM;
+
+/******************************************************************************
+ *	'bridge in' create Cmd Q
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_SIZE_T			uQueueSize;
+}PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE;
+
+
+/******************************************************************************
+ *	'bridge in' destroy Cmd Q
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	PVRSRV_QUEUE_INFO	*psQueueInfo;
+}PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE;
+
+
+/******************************************************************************
+ *	'bridge in' get full map data
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA_TAG
+{
+	IMG_HANDLE			hMHandle;	 /* Handle associated with the memory that needs to be mapped */
+} PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA;
+
+
+/******************************************************************************
+ *	'bridge in' get full map data
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA_TAG
+{
+	IMG_HANDLE			hMHandle;	 /* Handle associated with the memory that needs to be mapped */
+} PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA;
+
+
+/******************************************************************************
+ *	'bridge in' reserve vm
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG
+{
+	IMG_HANDLE			hDevMemHeap;
+	IMG_DEV_VIRTADDR	*psDevVAddr;
+	IMG_SIZE_T			uSize;
+	IMG_SIZE_T			uAlignment;
+}PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM;
+
+/******************************************************************************
+ *	'bridge out' connect to services
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT8		ui8KernelArch;
+	IMG_UINT64		hKernelServices; /* actually a IMG_HANDLE retrurnd from KM */
+}PVRSRV_BRIDGE_OUT_CONNECT_SERVICES;
+
+/******************************************************************************
+ *	'bridge out' reserve vm
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM_TAG
+{
+	PVRSRV_ERROR            eError;
+	IMG_HANDLE		hKernelMemInfo;
+	IMG_HANDLE		hKernelSyncInfo;
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM;
+
+
+/******************************************************************************
+ *	'bridge in' free vm
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM_TAG
+{
+	IMG_HANDLE		hKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+}PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM;
+
+/******************************************************************************
+ *	'bridge in' map dev memory allocation to another heap
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY_TAG
+{
+	IMG_HANDLE				hKernelMemInfo;
+	IMG_HANDLE				hDstDevMemHeap;
+}PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY;
+
+/******************************************************************************
+ *	'bridge out' map dev memory allocation to another heap
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_CLIENT_MEM_INFO	sDstClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sDstClientSyncInfo;
+}PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY;
+
+
+/******************************************************************************
+ *	'bridge in' unmap dev memory allocation
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY_TAG
+{
+	IMG_HANDLE		hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY;
+
+
+/******************************************************************************
+ *	'bridge in' map pages
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY_TAG
+{
+	IMG_HANDLE	hKernelMemInfo;
+	IMG_SYS_PHYADDR *psSysPAddr;
+	IMG_UINT32       ui32Flags;
+}PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY;
+
+/******************************************************************************
+ *	'bridge in' unmap pages
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY_TAG
+{
+	IMG_UINT32					ui32BridgeFlags; /* Must be first member of structure */
+	PVRSRV_CLIENT_MEM_INFO		sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO		sClientSyncInfo;
+	IMG_UINT32					ui32Flags;
+}PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY;
+
+/******************************************************************************
+ *	'bridge in' map device class buffer pages
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY_TAG
+{
+	IMG_HANDLE		hDeviceClassBuffer;
+	IMG_HANDLE		hDevMemContext;
+}PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY;
+
+
+/******************************************************************************
+ *	'bridge out' map device class buffer pages
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+	IMG_HANDLE		hKernelMemInfo;
+	IMG_HANDLE				hMappingInfo;
+}PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY;
+
+
+/******************************************************************************
+ *	'bridge in' unmap device class buffer pages
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY_TAG
+{
+	IMG_HANDLE		hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY;
+
+
+/******************************************************************************
+ *	'bridge in' pdump memory poll
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_MEMPOL_TAG
+{
+	IMG_HANDLE			hKernelMemInfo;
+	IMG_UINT32			ui32Offset;
+	IMG_UINT32			ui32Value;
+	IMG_UINT32			ui32Mask;
+	PDUMP_POLL_OPERATOR	eOperator;
+	IMG_UINT32			ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPOL;
+
+/******************************************************************************
+ *	'bridge in' pdump sync poll
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL_TAG
+{
+	IMG_HANDLE		hKernelSyncInfo;
+	IMG_BOOL		bIsRead;
+	IMG_BOOL		bUseLastOpDumpVal;
+	IMG_UINT32		ui32Value;
+	IMG_UINT32		ui32Mask;
+}PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL;
+
+
+/******************************************************************************
+ *	'bridge in' pdump dump memory
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM_TAG
+{
+	IMG_HANDLE		hLinAddr;
+	IMG_HANDLE		hAltLinAddr;
+	IMG_HANDLE		hKernelMemInfo;
+	IMG_UINT32		ui32Offset;
+	IMG_UINT32		ui32Bytes;
+	IMG_UINT32		ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM;
+
+
+/******************************************************************************
+ *	'bridge in' pdump dump sync
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC_TAG
+{
+	IMG_HANDLE		hAltLinAddr;
+	IMG_HANDLE		hKernelSyncInfo;
+	IMG_UINT32		ui32Offset;
+	IMG_UINT32		ui32Bytes;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC;
+
+
+/******************************************************************************
+ *	'bridge in' pdump dump reg
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_DUMPREG_TAG
+{
+	IMG_HANDLE		hDevCookie;
+	PVRSRV_HWREG	sHWReg;
+	IMG_UINT32		ui32Flags;
+	IMG_CHAR		szRegRegion[32];
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+
+/******************************************************************************
+ *	'bridge in' pdump dump reg
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG
+{
+	IMG_HANDLE		hDevCookie;
+	PVRSRV_HWREG	sHWReg;
+	IMG_UINT32		ui32Mask;
+	IMG_UINT32		ui32Flags;
+	IMG_CHAR		szRegRegion[32];
+}PVRSRV_BRIDGE_IN_PDUMP_REGPOL;
+
+/******************************************************************************
+ *	'bridge in' pdump dump PD reg
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG_TAG
+{
+	PVRSRV_HWREG	sHWReg;
+	IMG_UINT32		ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG;
+
+/******************************************************************************
+ *	'bridge in' pdump dump mem pages
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hKernelMemInfo;
+	IMG_DEV_PHYADDR		*pPages;
+	IMG_UINT32			ui32NumPages;
+	IMG_DEV_VIRTADDR	sDevVAddr;
+	IMG_UINT32			ui32Start;
+	IMG_UINT32			ui32Length;
+	IMG_UINT32			ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES;
+
+/******************************************************************************
+ *	'bridge in' pdump dump comment
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_COMMENT_TAG
+{
+	IMG_CHAR		szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+	IMG_UINT32		ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_COMMENT;
+
+
+/******************************************************************************
+ *	'bridge in' pdump set frame
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_SETFRAME_TAG
+{
+	IMG_UINT32		ui32Frame;
+}PVRSRV_BRIDGE_IN_PDUMP_SETFRAME;
+
+
+/******************************************************************************
+ *	'bridge in' pdump dump bitmap
+ *****************************************************************************/
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_BITMAP_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_CHAR			szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+	IMG_UINT32			ui32FileOffset;
+	IMG_UINT32			ui32Width;
+	IMG_UINT32			ui32Height;
+	IMG_UINT32			ui32StrideInBytes;
+	IMG_DEV_VIRTADDR	sDevBaseAddr;
+	IMG_HANDLE			hDevMemContext;
+	IMG_UINT32			ui32Size;
+	PDUMP_PIXEL_FORMAT	ePixelFormat;
+	PDUMP_MEM_FORMAT	eMemFormat;
+	IMG_UINT32			ui32Flags;
+}PVRSRV_BRIDGE_IN_PDUMP_BITMAP;
+
+
+/******************************************************************************
+ *	'bridge in' pdump dump read reg
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_READREG_TAG
+{
+	IMG_HANDLE		hDevCookie;
+	IMG_CHAR		szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+	IMG_UINT32		ui32FileOffset;
+	IMG_UINT32		ui32Address;
+	IMG_UINT32		ui32Size;
+	IMG_UINT32		ui32Flags;
+	IMG_CHAR		szRegRegion[32];
+}PVRSRV_BRIDGE_IN_PDUMP_READREG;
+
+/******************************************************************************
+ *	'bridge in' pdump dump driver-info
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO_TAG
+{
+	IMG_CHAR		szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+	IMG_BOOL		bContinuous;
+}PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR_TAG
+{
+	IMG_HANDLE		hKernelMemInfo;
+	IMG_UINT32		ui32Offset;
+	IMG_DEV_PHYADDR	sPDDevPAddr;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR;
+
+/******************************************************************************
+ *	'bridge in' pdump cycle count register read
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_PDUM_IN_CYCLE_COUNT_REG_READ_TAG
+{
+	IMG_HANDLE		hDevCookie;
+	IMG_UINT32		ui32RegOffset;
+	IMG_BOOL		bLastFrame;
+}PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ;
+
+/*****************************************************************************
+ * Output structures for BRIDGEs
+ ****************************************************************************/
+
+/******************************************************************************
+ *	'bridge out' enum. devices
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_ENUMDEVICE_TAG
+{
+	PVRSRV_ERROR				eError;
+	IMG_UINT32					ui32NumDevices;
+	PVRSRV_DEVICE_IDENTIFIER	asDeviceIdentifier[PVRSRV_MAX_DEVICES];
+}PVRSRV_BRIDGE_OUT_ENUMDEVICE;
+
+
+/******************************************************************************
+ *	'bridge out' acquire device info
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hDevCookie;
+} PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO;
+
+
+/******************************************************************************
+ *	'bridge out' enum. class devices
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_ENUMCLASS_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32NumDevices;
+	IMG_UINT32		ui32DevID[PVRSRV_MAX_DEVICES];
+}PVRSRV_BRIDGE_OUT_ENUMCLASS;
+
+
+/******************************************************************************
+ *	'bridge in' open display class devices
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE_TAG
+{
+	IMG_UINT32		ui32DeviceID;
+	IMG_HANDLE		hDevCookie;
+}PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE;
+
+/******************************************************************************
+ *	'bridge out' open display class devices
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hDeviceKM;
+}PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE;
+
+
+/******************************************************************************
+ *	'bridge in' wrap pages
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hDevMemContext;
+	IMG_VOID				*pvLinAddr;
+	IMG_SIZE_T			uByteSize;
+	IMG_SIZE_T			uPageOffset;
+	IMG_BOOL			bPhysContig;
+	IMG_UINT32			ui32NumPageTableEntries;
+	IMG_SYS_PHYADDR		*psSysPAddr;
+	IMG_UINT32			ui32Flags;
+}PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY;
+
+/******************************************************************************
+ *	'bridge out' wrap pages
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+}PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY;
+
+/******************************************************************************
+ *	'bridge in' unwrap pages
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY_TAG
+{
+	IMG_HANDLE hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY;
+
+
+#define PVRSRV_MAX_DC_DISPLAY_FORMATS			10
+#define PVRSRV_MAX_DC_DISPLAY_DIMENSIONS		10
+#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS			4
+#define PVRSRV_MAX_DC_CLIP_RECTS				32
+
+/******************************************************************************
+ *	'bridge out' enum display class formats
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32Count;
+	DISPLAY_FORMAT	asFormat[PVRSRV_MAX_DC_DISPLAY_FORMATS];
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS;
+
+
+/******************************************************************************
+ *	'bridge in' enum display class dims
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	DISPLAY_FORMAT	sFormat;
+}PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS;
+
+
+/******************************************************************************
+ *	'bridge out' enum display class dims
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32Count;
+	DISPLAY_DIMS	asDim[PVRSRV_MAX_DC_DISPLAY_DIMENSIONS];
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS;
+
+
+/******************************************************************************
+ *	'bridge out' enum display class dims
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO_TAG
+{
+	PVRSRV_ERROR	eError;
+	DISPLAY_INFO	sDisplayInfo;
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO;
+
+
+/******************************************************************************
+ *	'bridge out' get display class system buffer
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hBuffer;
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER;
+
+
+/******************************************************************************
+ *	'bridge in' create swap chain
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+	IMG_HANDLE					hDeviceKM;
+	DISPLAY_SURF_ATTRIBUTES		sDstSurfAttrib;
+	DISPLAY_SURF_ATTRIBUTES		sSrcSurfAttrib;
+	IMG_UINT32					ui32Flags;
+	IMG_UINT32					ui32BufferCount;
+	IMG_UINT32					ui32OEMFlags;
+	IMG_UINT32					ui32SwapChainID;
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	IMG_INT32					i32TimelineFd;
+	IMG_INT32					i32Unused;
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE) */
+} PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+/******************************************************************************
+ *	'bridge out' create swap chain
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32SwapChainID;
+	IMG_HANDLE		hSwapChain;
+} PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+/******************************************************************************
+ *	'bridge in' destroy swap chain
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_HANDLE		hSwapChain;
+} PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN;
+
+
+/******************************************************************************
+ *	'bridge in' set DST/SRC rect
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_HANDLE		hSwapChain;
+	IMG_RECT		sRect;
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT;
+
+
+/******************************************************************************
+ *	'bridge in' set DST/SRC colourkey
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_HANDLE		hSwapChain;
+	IMG_UINT32		ui32CKColour;
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY;
+
+
+/******************************************************************************
+ *	'bridge in' get buffers (from swapchain)
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_HANDLE		hSwapChain;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS;
+
+
+/******************************************************************************
+ *	'bridge out' get buffers (from swapchain)
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32BufferCount;
+	IMG_HANDLE		ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+	IMG_SYS_PHYADDR	asPhyAddr[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS;
+
+
+/******************************************************************************
+ *	'bridge in' swap to buffer
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_HANDLE		hBuffer;
+	IMG_HANDLE		hPrivateTag;
+	IMG_UINT32		ui32SwapInterval;
+	IMG_UINT32		ui32ClipRectCount;
+	IMG_RECT		sClipRect[PVRSRV_MAX_DC_CLIP_RECTS];
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER;
+
+
+/******************************************************************************
+ *	'bridge in' swap to buffer 2
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_HANDLE		hSwapChain;
+
+	IMG_UINT32		ui32SwapInterval;
+	IMG_UINT32		ui32NumMemInfos;
+	IMG_HANDLE		hKernelMemInfos;
+	IMG_HANDLE		hKernelSyncInfos;
+	IMG_UINT32		ui32PrivDataLength;
+	IMG_HANDLE		hPrivData;
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2;
+
+
+/******************************************************************************
+ *	'bridge out' swap to buffer 2
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_SWAP_DISPCLASS_TO_BUFFER2_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hFence;
+} PVRSRV_BRIDGE_OUT_SWAP_DISPCLASS_TO_BUFFER2;
+
+
+/******************************************************************************
+ *	'bridge in' swap to system buffer (primary)
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_HANDLE		hSwapChain;
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM;
+
+
+/******************************************************************************
+ *	'bridge in' open buffer class device
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+	IMG_UINT32		ui32DeviceID;
+	IMG_HANDLE		hDevCookie;
+} PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE;
+
+
+/******************************************************************************
+ *	'bridge out' open buffer class device
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hDeviceKM;
+} PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE;
+
+
+/******************************************************************************
+ *	'bridge out' get buffer class info
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO_TAG
+{
+	PVRSRV_ERROR	eError;
+	BUFFER_INFO		sBufferInfo;
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO;
+
+
+/******************************************************************************
+ *	'bridge in' get buffer class buffer
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER_TAG
+{
+	IMG_HANDLE		hDeviceKM;
+	IMG_UINT32		ui32BufferIndex;
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER;
+
+
+/******************************************************************************
+ *	'bridge out' get buffer class buffer
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hBuffer;
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER;
+
+
+/******************************************************************************
+ *	'bridge out' get heap info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_UINT32			ui32ClientHeapCount;
+	PVRSRV_HEAP_INFO	sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO;
+
+
+/******************************************************************************
+ *	'bridge out' create device memory context
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_UINT32			ui32ClientHeapCount;
+	IMG_HANDLE			hDevMemContext;
+	PVRSRV_HEAP_INFO	sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT;
+
+
+/******************************************************************************
+ *	'bridge out' create device memory context
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hDevMemHeap;
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP;
+
+
+/******************************************************************************
+ *	'bridge out' alloc device memory
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM_TAG
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+} PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+
+
+/******************************************************************************
+ *	'bridge out' free device memory
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_FREEDEVICEMEM_TAG
+{
+	PVRSRV_ERROR            eError;
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	IMG_UINT32				ui32TimeToDevUnmap;
+#endif
+
+} PVRSRV_BRIDGE_OUT_FREEDEVICEMEM;
+
+
+/******************************************************************************
+ *	'bridge out' export device memory
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+	IMG_UINT64		ui64Stamp;
+#endif
+} PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM;
+
+
+/******************************************************************************
+ *	'bridge out' map ion handle
+ *****************************************************************************/
+typedef struct IMG_COMPAT _PVRSRV_BRIDGE_OUT_MAP_ION_HANDLE_
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_CLIENT_MEM_INFO	sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO	sClientSyncInfo;
+	IMG_SIZE_T		uiIonBufferSize;
+} PVRSRV_BRIDGE_OUT_MAP_ION_HANDLE;
+
+/******************************************************************************
+ *	'bridge out' map dmabuf
+ *****************************************************************************/
+typedef struct IMG_COMPAT _PVRSRV_BRIDGE_OUT_MAP_DMABUF_
+{
+	PVRSRV_ERROR            eError;
+	IMG_HANDLE		hKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+	IMG_SIZE_T		uiSize;
+	IMG_SIZE_T		uiOffset;
+} PVRSRV_BRIDGE_OUT_MAP_DMABUF;
+
+/******************************************************************************
+ *	'bridge out' map meminfo to user mode
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER_TAG
+{
+	PVRSRV_ERROR			eError;
+	IMG_PVOID				pvLinAddr;
+	IMG_HANDLE				hMappingInfo;
+}PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER;
+
+
+/******************************************************************************
+ *	'bridge out' get free device memory
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_SIZE_T		uTotal;
+	IMG_SIZE_T		uFree;
+	IMG_SIZE_T		uLargestBlock;
+} PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+
+
+//#ifdef LINUX
+/******************************************************************************
+ *	'bridge out' get full map data
+ *****************************************************************************/
+#include "pvrmmap.h"
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA_TAG
+{
+    PVRSRV_ERROR	eError;
+
+    /* This is a the offset you should pass to mmap(2) so that
+     * the driver can look up the full details for the mapping
+     * request. */
+     IMG_UINTPTR_T	uiMMapOffset;
+
+    /* This is the byte offset you should add to the mapping you
+     * get from mmap */
+    IMG_UINTPTR_T	uiByteOffset;
+
+    /* This is the real size of the mapping that will be created
+     * which should be passed to mmap _and_ munmap. */
+    IMG_SIZE_T		uiRealByteSize;
+
+    /* User mode address associated with mapping */
+    IMG_UINTPTR_T	uiUserVAddr;
+
+} PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA_TAG
+{
+    PVRSRV_ERROR	eError;
+
+    /* Flag that indicates whether the mapping should be destroyed */
+    IMG_BOOL		bMUnmap;
+
+    /* User mode address associated with mapping */
+    IMG_UINTPTR_T	uiUserVAddr;
+
+    /* Size of mapping */
+    IMG_SIZE_T		uiRealByteSize;
+} PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA;
+//#endif
+
+typedef struct PVRSRV_BRIDGE_IN_COMPAT_CHECK
+{
+	IMG_UINT32		ui32DDKVersion;
+	IMG_UINT32		ui32DDKBuild;
+#if defined(SUPPORT_TI_VERSION_STRING)
+	IMG_CHAR 		szTIVersion[64];
+#endif
+} PVRSRV_BRIDGE_IN_COMPAT_CHECK;
+
+/******************************************************************************
+ *	'bridge in' get misc info
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_GET_MISC_INFO_TAG
+{
+	PVRSRV_MISC_INFO	sMiscInfo;
+}PVRSRV_BRIDGE_IN_GET_MISC_INFO;
+
+
+/******************************************************************************
+ *	'bridge out' get misc info
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_GET_MISC_INFO_TAG
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_MISC_INFO	sMiscInfo;
+}PVRSRV_BRIDGE_OUT_GET_MISC_INFO;
+
+
+/******************************************************************************
+ *	'bridge in' get misc info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO_TAG
+{
+	PVRSRV_MISC_INFO	sMiscInfo;
+}PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO;
+
+
+/******************************************************************************
+ *	'bridge out' get misc info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO_TAG
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_MISC_INFO	sMiscInfo;
+}PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO;
+
+
+/******************************************************************************
+ *	'bridge out' PDUMP is capturing
+ *****************************************************************************/
+
+typedef struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_BOOL		bIsCapturing;
+} PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING;
+
+/******************************************************************************
+ *	'bridge in' get FB mem stats
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GET_FB_STATS_TAG
+{
+	IMG_SIZE_T uTotal;
+	IMG_SIZE_T uAvailable;
+} PVRSRV_BRIDGE_IN_GET_FB_STATS;
+
+
+/******************************************************************************
+ *	'bridge in' Map CPU Physical to User Space
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_SYS_PHYADDR		sSysPhysAddr;
+	IMG_UINT32			uiSizeInBytes;
+} PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE;
+
+
+/******************************************************************************
+ *	'bridge out' Map CPU Physical to User Space
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE_TAG
+{
+	IMG_PVOID			pvUserAddr;
+	IMG_UINT32			uiActualSize;
+	IMG_PVOID			pvProcess;
+} PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE;
+
+
+/******************************************************************************
+ *	'bridge in' Unmap CPU Physical to User Space
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_PVOID			pvUserAddr;
+	IMG_PVOID			pvProcess;
+} PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE;
+
+
+/******************************************************************************
+ *	'bridge out' Get user space pointer to Phys to Lin lookup table
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP_TAG
+{
+	IMG_PVOID			*ppvTbl;
+	IMG_UINT32			uiTblSize;
+} PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP;
+
+
+/******************************************************************************
+ *	'bridge in' Register RTSIM process thread
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_PVOID			pvProcess;
+} PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS;
+
+
+/******************************************************************************
+ *	'bridge out' Register RTSIM process thread
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS_TAG
+{
+	IMG_SYS_PHYADDR		sRegsPhysBase;			/*!< Physical address of current device register */
+	IMG_VOID			*pvRegsBase;			/*!< User mode linear address of SGX device registers */
+	IMG_PVOID			pvProcess;
+	IMG_UINT32			ulNoOfEntries;
+	IMG_PVOID			pvTblLinAddr;
+} PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS;
+
+
+/******************************************************************************
+ *	'bridge in' Unregister RTSIM process thread
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_PVOID			pvProcess;
+	IMG_VOID			*pvRegsBase;			/*!< User mode linear address of SGX device registers */
+
+} PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS;
+
+/******************************************************************************
+ *	'bridge in' process simulator ISR event
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_UINT32			ui32StatusAndMask;
+	PVRSRV_ERROR 		eError;
+} PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT;
+
+/******************************************************************************
+ *	'bridge in' initialisation server disconnect
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT_TAG
+{
+	IMG_BOOL		bInitSuccesful;
+} PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM_TAG
+{
+    IMG_UINT32 ui32Flags;
+    IMG_SIZE_T uSize;
+}PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM_TAG
+{
+	PVRSRV_ERROR            eError;
+	IMG_HANDLE 		hKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+}PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM_TAG
+{
+	IMG_HANDLE		hKernelMemInfo;
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+}PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM_TAG
+{
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM_TAG
+{
+	IMG_HANDLE hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM_TAG
+{
+	PVRSRV_CLIENT_MEM_INFO  sClientMemInfo;
+	PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+	IMG_HANDLE		hKernelMemInfo;
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM_TAG
+{
+	PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM_TAG
+{
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAI_TAG
+{
+	IMG_HANDLE		hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN_TAG
+{
+	PVRSRV_EVENTOBJECT	sEventObject;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN;
+
+typedef struct	IMG_COMPAT PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN_TAG
+{
+	IMG_HANDLE		hOSEvent;
+	PVRSRV_ERROR	eError;
+} PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE_TAG
+{
+	PVRSRV_EVENTOBJECT	sEventObject;
+	IMG_HANDLE			hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ
+{
+	IMG_HANDLE		hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS_TAG
+{
+	IMG_HANDLE		hKernelSyncInfoModObj;
+	IMG_HANDLE		hKernelSyncInfo;
+	IMG_UINT32		ui32ModifyFlags;
+} PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS_TAG
+{
+	IMG_HANDLE		hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS_TAG
+{
+	PVRSRV_ERROR	eError;
+	/* The following variable are used to return the PRE-INCREMENTED op vals */
+	IMG_UINT32		ui32ReadOpsPending;
+	IMG_UINT32		ui32WriteOpsPending;
+	IMG_UINT32		ui32ReadOps2Pending;
+} PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_TAKE_TOKEN_TAG
+{
+	IMG_HANDLE		hKernelSyncInfo;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_TAKE_TOKEN;
+
+typedef struct PVRSRV_BRIDGE_OUT_SYNC_OPS_TAKE_TOKEN_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32		ui32ReadOpsPending;
+	IMG_UINT32		ui32WriteOpsPending;
+	IMG_UINT32		ui32ReadOps2Pending;
+} PVRSRV_BRIDGE_OUT_SYNC_OPS_TAKE_TOKEN;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN_TAG
+{
+	IMG_HANDLE		hKernelSyncInfo;
+	IMG_UINT32		ui32ReadOpsPendingSnapshot;
+	IMG_UINT32		ui32WriteOpsPendingSnapshot;
+	IMG_UINT32		ui32ReadOps2PendingSnapshot;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ_TAG
+{
+	IMG_HANDLE		hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA_TAG
+{
+	IMG_HANDLE		hKernelSyncInfo;
+	IMG_UINT32		ui32Delta;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA;
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO_TAG
+{
+	IMG_HANDLE		hDevCookie;
+} PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_HANDLE		hKernelSyncInfo;
+} PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SYNC_INFO_TAG
+{
+	IMG_HANDLE		hKernelSyncInfo;
+} PVRSRV_BRIDGE_IN_FREE_SYNC_INFO;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_CHG_DEV_MEM_ATTRIBS_TAG
+{
+	IMG_SID			hKernelMemInfo;
+	IMG_UINT32		ui32Attribs;
+} PVRSRV_BRIDGE_IN_CHG_DEV_MEM_ATTRIBS;
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_BRIDGE_H__ */
+
+/******************************************************************************
+ End of file (pvr_bridge.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/pvr/services4/include/pvr_bridge_km.h b/drivers/gpu/pvr/services4/include/pvr_bridge_km.h
new file mode 100644
index 0000000..7dc4352
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/pvr_bridge_km.h
@@ -0,0 +1,422 @@
+/*************************************************************************/ /*!
+@Title          PVR Bridge Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the PVR Bridge code
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __PVR_BRIDGE_KM_H_
+#define __PVR_BRIDGE_KM_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+/******************************************************************************
+ * Function prototypes
+ *****************************************************************************/
+#if defined(__linux__)
+PVRSRV_ERROR LinuxBridgeInit(IMG_VOID);
+IMG_VOID LinuxBridgeDeInit(IMG_VOID);
+
+#if defined(SUPPORT_MEMINFO_IDS)
+extern IMG_UINT64 g_ui64MemInfoID;
+#endif
+
+#endif
+IMG_IMPORT
+IMG_VOID IMG_CALLCONV PVRSRVCompatCheckKM(PVRSRV_BRIDGE_IN_COMPAT_CHECK *psUserModeDDKDetails, PVRSRV_BRIDGE_RETURN *psRetOUT);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+												   PVRSRV_DEVICE_IDENTIFIER *psDevIdList);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM(IMG_UINT32			uiDevIndex,
+													PVRSRV_DEVICE_TYPE	eDeviceType,
+													IMG_HANDLE			*phDevCookie);
+							
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T uQueueSize,
+													 PVRSRV_QUEUE_INFO **ppsQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+													PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE					hDevCookie,
+														 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+														 IMG_HANDLE					*phDevMemContext,
+														 IMG_UINT32					*pui32ClientHeapCount,
+														 PVRSRV_HEAP_INFO			*psHeapInfo,
+														 IMG_BOOL					*pbCreated,
+														 IMG_BOOL					*pbShared);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+														  IMG_HANDLE hDevMemContext,
+														  IMG_BOOL *pbDestroyed);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE				hDevCookie,
+															IMG_HANDLE			hDevMemContext,
+															IMG_UINT32			*pui32ClientHeapCount,
+															PVRSRV_HEAP_INFO	*psHeapInfo,
+															IMG_BOOL 			*pbShared
+					);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE					hDevCookie,
+												 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												 IMG_HANDLE					hDevMemHeap,
+												 IMG_UINT32					ui32Flags,
+												 IMG_SIZE_T					ui32Size,
+												 IMG_SIZE_T					ui32Alignment,
+												 IMG_PVOID					pvPrivData,
+												 IMG_UINT32					ui32PrivDataLength,
+												 IMG_UINT32					ui32ChunkSize,
+												 IMG_UINT32					ui32NumVirtChunks,
+												 IMG_UINT32					ui32NumPhysChunks,
+												 IMG_BOOL					*pabMapChunk,
+												 PVRSRV_KERNEL_MEM_INFO		**ppsMemInfo);
+
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+	#define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+								   chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo, logStr) \
+		(PVR_TRACE(("PVRSRVAllocDeviceMemKM(" #devCookie ", " #perProc ", " #devMemHeap ", " #flags ", " #size \
+			", " #alignment "," #memInfo "): " logStr " (size = 0x%x)", size)),\
+			_PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+									chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo))
+#else
+	#define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+								   chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo, logStr) \
+			_PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, privdata, privdatalength, \
+									chunksize, numvirtchunks, numphyschunks, mapchunk, memInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE			hDevCookie,
+												PVRSRV_KERNEL_MEM_INFO	*psMemInfo);
+
+#if defined(SUPPORT_ION)
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVMapIonHandleKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+								  IMG_HANDLE hDevCookie,
+								  IMG_HANDLE hDevMemHeap,
+								  IMG_UINT32 ui32NumFDs,
+								  IMG_INT32  *pai32BufferFDs,
+								  IMG_UINT32 ui32Flags,
+								  IMG_UINT32 ui32ChunkCount,
+								  IMG_SIZE_T *pauiOffset,
+								  IMG_SIZE_T *pauiSize,
+								  IMG_SIZE_T *puiIonBufferSize,
+								  PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo,
+								  IMG_UINT64 *pui64Stamp);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapIonHandleKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+#endif /* SUPPORT_ION */
+
+#if defined(SUPPORT_DMABUF)
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVMapDmaBufKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+								  IMG_HANDLE hDevCookie,
+								  IMG_HANDLE hDevMemHeap,
+								  IMG_UINT32 ui32Flags,
+								  IMG_INT32 ui32DmaBufFD,
+								  IMG_SIZE_T uiDmaBufOffset,
+								  IMG_SIZE_T uiDmaBufSize,
+								  PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo,
+								  IMG_SIZE_T *puiSize,
+								  IMG_SIZE_T *puiMemInfoOffset,
+								  IMG_UINT64 *pui64Stamp);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDmaBufKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+#endif /* SUPPORT_DMABUF */
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE			hDevCookie,
+												PVRSRV_KERNEL_MEM_INFO	*psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMemKM(IMG_HANDLE		hDevMemHeap,
+														 IMG_DEV_VIRTADDR	*psDevVAddr,
+														 IMG_SIZE_T			ui32Size,
+														 IMG_SIZE_T			ui32Alignment,
+														 PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMemKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												  PVRSRV_KERNEL_MEM_INFO	*psSrcMemInfo,
+												  IMG_HANDLE				hDstDevMemHeap,
+												  PVRSRV_KERNEL_MEM_INFO	**ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE				hDevCookie,
+												PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												IMG_HANDLE				hDevMemContext,
+												IMG_SIZE_T 				ui32ByteSize, 
+												IMG_SIZE_T				ui32PageOffset,
+												IMG_BOOL				bPhysContig,
+												IMG_SYS_PHYADDR	 		*psSysAddr,
+												IMG_VOID 				*pvLinAddr,
+												IMG_UINT32				ui32Flags,
+												PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+								 IMG_UINT32 *pui32DevCount,
+								 IMG_UINT32 *pui32DevID );
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								  IMG_UINT32				ui32DeviceID,
+								  IMG_HANDLE 				hDevCookie,
+								  IMG_HANDLE 				*phDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM(IMG_HANDLE hDeviceKM,
+								   IMG_UINT32 *pui32Count,
+								   DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM(IMG_HANDLE hDeviceKM,
+								DISPLAY_FORMAT *psFormat,
+								IMG_UINT32 *pui32Count,
+								DISPLAY_DIMS *psDim);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(IMG_HANDLE hDeviceKM,
+									   IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM(IMG_HANDLE hDeviceKM,
+							   DISPLAY_INFO *psDisplayInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+									   IMG_HANDLE				hDeviceKM,
+									   IMG_UINT32				ui32Flags,
+									   DISPLAY_SURF_ATTRIBUTES	*psDstSurfAttrib,
+									   DISPLAY_SURF_ATTRIBUTES	*psSrcSurfAttrib,
+									   IMG_UINT32				ui32BufferCount,
+									   IMG_UINT32				ui32OEMFlags,
+									   IMG_HANDLE				*phSwapChain,
+									   IMG_UINT32				*pui32SwapChainID
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+									  ,IMG_INT32				i32TimelineFd
+#endif
+									  );
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE	hSwapChain);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChain,
+								  IMG_RECT	*psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChain,
+								  IMG_RECT	*psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE	hDeviceKM,
+									   IMG_HANDLE	hSwapChain,
+									   IMG_UINT32	ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE		hSwapChain,
+									IMG_UINT32		ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChain,
+								  IMG_UINT32	*pui32BufferCount,
+								  IMG_HANDLE	*phBuffer,
+								  IMG_SYS_PHYADDR *psPhyAddr);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hBuffer,
+									IMG_UINT32	ui32SwapInterval,
+									IMG_HANDLE	hPrivateTag,
+									IMG_UINT32	ui32ClipRectCount,
+									IMG_RECT	*psClipRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE	hDeviceKM,
+									 IMG_HANDLE	hBuffer,
+									 IMG_UINT32	ui32SwapInterval,
+									 PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
+									 PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
+									 IMG_UINT32	ui32NumMemSyncInfos,
+									 IMG_PVOID	pvPrivData,
+									 IMG_UINT32	ui32PrivDataLength,
+									 IMG_HANDLE	*phFence);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								  IMG_UINT32				ui32DeviceID,
+								  IMG_HANDLE				hDevCookie,
+								  IMG_HANDLE				*phDeviceKM);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM(IMG_HANDLE	hDeviceKM,
+							   BUFFER_INFO	*psBufferInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM(IMG_HANDLE	hDeviceKM,
+								 IMG_UINT32	ui32BufferIndex,
+								 IMG_HANDLE	*phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+													   IMG_HANDLE				hDevMemContext,
+													   IMG_HANDLE				hDeviceClassBuffer,
+													   PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo,
+													   IMG_HANDLE				*phOSMapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVChangeDeviceMemoryAttributesKM(IMG_HANDLE hKernelMemInfo,
+															   IMG_UINT32 ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+												   IMG_SIZE_T *pui32Total,
+												   IMG_SIZE_T *pui32Free,
+												   IMG_SIZE_T *pui32LargestBlock);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE					hDevCookie,
+												IMG_HANDLE					hDevMemContext,
+												PVRSRV_KERNEL_SYNC_INFO	**ppsKernelSyncInfo);
+IMG_IMPORT
+IMG_VOID IMG_CALLCONV PVRSRVAcquireSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo);
+IMG_IMPORT
+IMG_VOID IMG_CALLCONV PVRSRVReleaseSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo);
+
+/*!
+ * *****************************************************************************
+ * @brief Allocates memory on behalf of a userspace process that is addressable
+ *        by ther kernel. The memory is suitable for mapping into
+ *        user space and it is possible to entirely dissociate the memory
+ *        from the userspace process via PVRSRVDissociateSharedSysMemoryKM.
+ *
+ * @param psPerProc
+ * @param ui32Flags
+ * @param ui32Size
+ * @param ppsKernelMemInfo
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+							 IMG_UINT32 				ui32Flags,
+							 IMG_SIZE_T 				ui32Size,
+							 PVRSRV_KERNEL_MEM_INFO		**ppsKernelMemInfo);
+
+/*!
+ * *****************************************************************************
+ * @brief Frees memory allocated via PVRSRVAllocSharedSysMemoryKM (Note you must
+ *        be sure any additional kernel references you created have been
+ *        removed before freeing the memory)
+ *
+ * @param psKernelMemInfo
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+/*!
+******************************************************************************
+
+ @brief	Dissociates memory from the process that allocates it.  Intended for
+ transfering the ownership of system memory from a particular process
+ to the kernel.  Unlike PVRSRVDissociateDeviceMemKM, ownership is not
+ transfered to the kernel context, so the Resource Manager will not
+ automatically clean up such memory.
+
+ @param	   psKernelMemInfo:
+
+ @return   PVRSRV_ERROR:
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PVR_BRIDGE_KM_H_ */
+
+/******************************************************************************
+ End of file (pvr_bridge_km.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/include/pvrmmap.h b/drivers/gpu/pvr/services4/include/pvrmmap.h
new file mode 100644
index 0000000..c18c872
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/pvrmmap.h
@@ -0,0 +1,73 @@
+/*************************************************************************/ /*!
+@Title          Main include file for PVRMMAP library.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __PVRMMAP_H__
+#define __PVRMMAP_H__
+
+/*!
+ **************************************************************************
+ @brief         map kernel memory into user memory. 
+
+ @param			hModule - a handle to the device supplying the kernel memory
+ @param			ppvLinAddr - pointer to where the user mode address should be placed
+ @param			pvLinAddrKM - the base of kernel address range to map
+ @param			phMappingInfo - pointer to mapping information handle
+ @param			hMHandle - handle associated with memory to be mapped
+
+ @return		PVRSRV_OK, or error code.
+ ***************************************************************************/
+
+PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_HANDLE *phMappingInfo, IMG_HANDLE hMHandle);
+
+
+/*!
+ **************************************************************************
+ @brief	        Removes a kernel to userspace memory mapping.
+
+ @param		hModule - a handle to the device supplying the kernel memory
+ @param		hMappingInfo - mapping information handle
+ @param		hMHandle - handle associated with memory to be mapped
+
+ @return	IMG_BOOL indicating success or otherwise.
+ ***************************************************************************/
+IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_HANDLE hMappingInfo, IMG_HANDLE hMHandle);
+
+#endif /* _PVRMMAP_H_ */
+
diff --git a/drivers/gpu/pvr/services4/include/pvrsrv_errors.h b/drivers/gpu/pvr/services4/include/pvrsrv_errors.h
new file mode 100644
index 0000000..2e95810
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/pvrsrv_errors.h
@@ -0,0 +1,311 @@
+/*************************************************************************/ /*!
+@Title          error code to string translation utility
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    error code to string translation utility
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__PVRSRV_ERRORS_H__)
+#define __PVRSRV_ERRORS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+	NOTE: TO BE INCLUDED ONLY ONCE IN THE UM AND KM SERVICES MODULES
+	PROVIDES IMPLEMENTATIONS OF
+
+	MUST BE KEPT IN SYNC WITH SERVICESEXT.H
+
+	PVRSRVGetErrorString
+	PVRSRVGetErrorStringKM
+	Specifically, we have
+
+	resources.c:
+	IMG_EXPORT
+	const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError)
+	{
+	#include "pvrsrv_errors.h"
+	}
+
+	pvrsrv.c:
+	IMG_EXPORT
+	const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
+	{
+	#include "pvrsrv_errors.h"
+	}
+*/
+	switch (eError)
+	{
+		case PVRSRV_OK:									return "No Errors";
+		case PVRSRV_ERROR_OUT_OF_MEMORY:				return "PVRSRV_ERROR_OUT_OF_MEMORY - Unable to allocate required memory";
+		case PVRSRV_ERROR_TOO_FEW_BUFFERS:				return "PVRSRV_ERROR_TOO_FEW_BUFFERS";
+		case PVRSRV_ERROR_INVALID_PARAMS:				return "PVRSRV_ERROR_INVALID_PARAMS";
+		case PVRSRV_ERROR_INIT_FAILURE:					return "PVRSRV_ERROR_INIT_FAILURE";
+		case PVRSRV_ERROR_CANT_REGISTER_CALLBACK:		return "PVRSRV_ERROR_CANT_REGISTER_CALLBACK";
+		case PVRSRV_ERROR_INVALID_DEVICE:				return "PVRSRV_ERROR_INVALID_DEVICE";
+		case PVRSRV_ERROR_NOT_OWNER:					return "PVRSRV_ERROR_NOT_OWNER";
+		case PVRSRV_ERROR_BAD_MAPPING:					return "PVRSRV_ERROR_BAD_MAPPING";
+		case PVRSRV_ERROR_TIMEOUT:						return "PVRSRV_ERROR_TIMEOUT";
+		case PVRSRV_ERROR_FLIP_CHAIN_EXISTS:			return "PVRSRV_ERROR_FLIP_CHAIN_EXISTS";
+		case PVRSRV_ERROR_INVALID_SWAPINTERVAL:			return "PVRSRV_ERROR_INVALID_SWAPINTERVAL";
+		case PVRSRV_ERROR_SCENE_INVALID:				return "PVRSRV_ERROR_SCENE_INVALID";
+		case PVRSRV_ERROR_STREAM_ERROR:					return "PVRSRV_ERROR_STREAM_ERROR";
+		case PVRSRV_ERROR_FAILED_DEPENDENCIES:			return "PVRSRV_ERROR_FAILED_DEPENDENCIES";
+		case PVRSRV_ERROR_CMD_NOT_PROCESSED:			return "PVRSRV_ERROR_CMD_NOT_PROCESSED";
+		case PVRSRV_ERROR_CMD_TOO_BIG:					return "PVRSRV_ERROR_CMD_TOO_BIG";
+		case PVRSRV_ERROR_DEVICE_REGISTER_FAILED:		return "PVRSRV_ERROR_DEVICE_REGISTER_FAILED";
+		case PVRSRV_ERROR_TOOMANYBUFFERS:				return "PVRSRV_ERROR_TOOMANYBUFFERS";
+		case PVRSRV_ERROR_NOT_SUPPORTED:				return "PVRSRV_ERROR_NOT_SUPPORTED - fix";
+		case PVRSRV_ERROR_PROCESSING_BLOCKED:			return "PVRSRV_ERROR_PROCESSING_BLOCKED";
+
+		case PVRSRV_ERROR_CANNOT_FLUSH_QUEUE:			return "PVRSRV_ERROR_CANNOT_FLUSH_QUEUE";
+		case PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE:		return "PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE";
+		case PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS:		return "PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS";
+		case PVRSRV_ERROR_RETRY:						return "PVRSRV_ERROR_RETRY";
+
+		case PVRSRV_ERROR_DDK_VERSION_MISMATCH:			return "PVRSRV_ERROR_DDK_VERSION_MISMATCH";
+		case PVRSRV_ERROR_BUILD_MISMATCH:				return "PVRSRV_ERROR_BUILD_MISMATCH";
+		case PVRSRV_ERROR_CORE_REVISION_MISMATCH:		return "PVRSRV_ERROR_CORE_REVISION_MISMATCH";
+
+		case PVRSRV_ERROR_UPLOAD_TOO_BIG:				return "PVRSRV_ERROR_UPLOAD_TOO_BIG";
+
+		case PVRSRV_ERROR_INVALID_FLAGS:				return "PVRSRV_ERROR_INVALID_FLAGS";
+		case PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS:	return "PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS";
+
+		case PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY:		return "PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY";
+		case PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR:			return "PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR";
+		case PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED:		return "PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED";
+
+		case PVRSRV_ERROR_BRIDGE_CALL_FAILED:			return "PVRSRV_ERROR_BRIDGE_CALL_FAILED";
+		case PVRSRV_ERROR_IOCTL_CALL_FAILED:			return "PVRSRV_ERROR_IOCTL_CALL_FAILED";
+
+		case PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND:		return "PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND";
+		case PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND:		return "PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND";
+		case PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT:return "PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT";
+
+		case PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND:			return "PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND";
+		case PVRSRV_ERROR_PCI_CALL_FAILED:				return "PVRSRV_ERROR_PCI_CALL_FAILED";
+		case PVRSRV_ERROR_PCI_REGION_TOO_SMALL:			return "PVRSRV_ERROR_PCI_REGION_TOO_SMALL";
+		case PVRSRV_ERROR_PCI_REGION_UNAVAILABLE:		return "PVRSRV_ERROR_PCI_REGION_UNAVAILABLE";
+		case PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH:		return "PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH";
+
+		case PVRSRV_ERROR_REGISTER_BASE_NOT_SET:		return "PVRSRV_ERROR_REGISTER_BASE_NOT_SET";
+
+        case PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE:       return "PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE";
+
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM:		return "PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM";
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY:	return "PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY";
+		case PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC:	return "PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC";
+		case PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR:		return "PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR";
+
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY:	return "PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY";
+		case PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY:	return "PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY";
+
+		case PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES:		return "PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES";
+		case PVRSRV_ERROR_FAILED_TO_FREE_PAGES:			return "PVRSRV_ERROR_FAILED_TO_FREE_PAGES";
+		case PVRSRV_ERROR_FAILED_TO_COPY_PAGES:			return "PVRSRV_ERROR_FAILED_TO_COPY_PAGES";
+		case PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES:			return "PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES";
+		case PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES:		return "PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES";
+		case PVRSRV_ERROR_STILL_MAPPED:					return "PVRSRV_ERROR_STILL_MAPPED";
+		case PVRSRV_ERROR_MAPPING_NOT_FOUND:			return "PVRSRV_ERROR_MAPPING_NOT_FOUND";
+		case PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT:	return "PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT";
+		case PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE:		return "PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE";
+
+		case PVRSRV_ERROR_INVALID_SEGMENT_BLOCK:		return "PVRSRV_ERROR_INVALID_SEGMENT_BLOCK";
+		case PVRSRV_ERROR_INVALID_SGXDEVDATA:			return "PVRSRV_ERROR_INVALID_SGXDEVDATA";
+		case PVRSRV_ERROR_INVALID_DEVINFO:				return "PVRSRV_ERROR_INVALID_DEVINFO";
+		case PVRSRV_ERROR_INVALID_MEMINFO:				return "PVRSRV_ERROR_INVALID_MEMINFO";
+		case PVRSRV_ERROR_INVALID_MISCINFO:				return "PVRSRV_ERROR_INVALID_MISCINFO";
+		case PVRSRV_ERROR_UNKNOWN_IOCTL:				return "PVRSRV_ERROR_UNKNOWN_IOCTL";
+		case PVRSRV_ERROR_INVALID_CONTEXT:				return "PVRSRV_ERROR_INVALID_CONTEXT";
+		case PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT:	return "PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT";
+		case PVRSRV_ERROR_INVALID_HEAP:					return "PVRSRV_ERROR_INVALID_HEAP";
+		case PVRSRV_ERROR_INVALID_KERNELINFO:			return "PVRSRV_ERROR_INVALID_KERNELINFO";
+		case PVRSRV_ERROR_UNKNOWN_POWER_STATE:			return "PVRSRV_ERROR_UNKNOWN_POWER_STATE";
+		case PVRSRV_ERROR_INVALID_HANDLE_TYPE:			return "PVRSRV_ERROR_INVALID_HANDLE_TYPE";
+		case PVRSRV_ERROR_INVALID_WRAP_TYPE:			return "PVRSRV_ERROR_INVALID_WRAP_TYPE";
+		case PVRSRV_ERROR_INVALID_PHYS_ADDR:			return "PVRSRV_ERROR_INVALID_PHYS_ADDR";
+		case PVRSRV_ERROR_INVALID_CPU_ADDR:				return "PVRSRV_ERROR_INVALID_CPU_ADDR";
+		case PVRSRV_ERROR_INVALID_HEAPINFO:				return "PVRSRV_ERROR_INVALID_HEAPINFO";
+		case PVRSRV_ERROR_INVALID_PERPROC:				return "PVRSRV_ERROR_INVALID_PERPROC";
+		case PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO:	return "PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO";
+		case PVRSRV_ERROR_INVALID_MAP_REQUEST:			return "PVRSRV_ERROR_INVALID_MAP_REQUEST";
+		case PVRSRV_ERROR_INVALID_UNMAP_REQUEST:		return "PVRSRV_ERROR_INVALID_UNMAP_REQUEST";
+		case PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP:	return "PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP";
+		case PVRSRV_ERROR_MAPPING_STILL_IN_USE:			return "PVRSRV_ERROR_MAPPING_STILL_IN_USE";
+
+		case PVRSRV_ERROR_EXCEEDED_HW_LIMITS:			return "PVRSRV_ERROR_EXCEEDED_HW_LIMITS";
+		case PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED:	return "PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED";
+
+		case PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA:return "PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA";
+		case PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT:		return "PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT";
+		case PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD:		return "PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD";
+		case PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD:		return "PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD";
+		case PVRSRV_ERROR_THREAD_READ_ERROR:			return "PVRSRV_ERROR_THREAD_READ_ERROR";
+		case PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER:return "PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER";
+		case PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR:		return "PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR";
+		case PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR:		return "PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR";
+		case PVRSRV_ERROR_ISR_ALREADY_INSTALLED:		return "PVRSRV_ERROR_ISR_ALREADY_INSTALLED";
+		case PVRSRV_ERROR_ISR_NOT_INSTALLED:			return "PVRSRV_ERROR_ISR_NOT_INSTALLED";
+		case PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT:return "PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT";
+		case PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO:		return "PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO";
+		case PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT:	return "PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT";
+		case PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES:		return "PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES";
+		case PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT:	return "PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT";
+		case PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE:	return "PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE";
+
+		case PVRSRV_ERROR_INVALID_CCB_COMMAND:			return "PVRSRV_ERROR_INVALID_CCB_COMMAND";
+
+		case PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE:		return "PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE";
+		case PVRSRV_ERROR_INVALID_LOCK_ID:				return "PVRSRV_ERROR_INVALID_LOCK_ID";
+		case PVRSRV_ERROR_RESOURCE_NOT_LOCKED:			return "PVRSRV_ERROR_RESOURCE_NOT_LOCKED";
+
+		case PVRSRV_ERROR_FLIP_FAILED:					return "PVRSRV_ERROR_FLIP_FAILED";
+		case PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED:		return "PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED";
+
+		case PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE:	return "PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE";
+
+		case PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED:	return "PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED";
+		case PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG:			return "PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG";
+		case PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG:	return "PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG";
+		case PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG:		return "PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG";
+
+		case PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID:	return "PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID";
+
+		case PVRSRV_ERROR_BLIT_SETUP_FAILED:			return "PVRSRV_ERROR_BLIT_SETUP_FAILED";
+
+		case PVRSRV_ERROR_PDUMP_NOT_AVAILABLE:			return "PVRSRV_ERROR_PDUMP_NOT_AVAILABLE";
+		case PVRSRV_ERROR_PDUMP_BUFFER_FULL:			return "PVRSRV_ERROR_PDUMP_BUFFER_FULL";
+		case PVRSRV_ERROR_PDUMP_BUF_OVERFLOW:			return "PVRSRV_ERROR_PDUMP_BUF_OVERFLOW";
+		case PVRSRV_ERROR_PDUMP_NOT_ACTIVE:				return "PVRSRV_ERROR_PDUMP_NOT_ACTIVE";
+		case PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES:return "PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES";
+
+		case PVRSRV_ERROR_MUTEX_DESTROY_FAILED:			return "PVRSRV_ERROR_MUTEX_DESTROY_FAILED";
+		case PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR:	return "PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR";
+
+		case PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE:	return "PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE";
+		case PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND:return "PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND";
+
+		case PVRSRV_ERROR_PROCESS_NOT_INITIALISED:		return "PVRSRV_ERROR_PROCESS_NOT_INITIALISED";
+		case PVRSRV_ERROR_PROCESS_NOT_FOUND:			return "PVRSRV_ERROR_PROCESS_NOT_FOUND";
+		case PVRSRV_ERROR_SRV_CONNECT_FAILED:			return "PVRSRV_ERROR_SRV_CONNECT_FAILED";
+		case PVRSRV_ERROR_SRV_DISCONNECT_FAILED:		return "PVRSRV_ERROR_SRV_DISCONNECT_FAILED";
+		case PVRSRV_ERROR_DEINT_PHASE_FAILED:			return "PVRSRV_ERROR_DEINT_PHASE_FAILED";
+		case PVRSRV_ERROR_INIT2_PHASE_FAILED:			return "PVRSRV_ERROR_INIT2_PHASE_FAILED";
+
+		case PVRSRV_ERROR_NO_DC_DEVICES_FOUND:			return "PVRSRV_ERROR_NO_DC_DEVICES_FOUND";
+		case PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE:		return "PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE";
+		case PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE:		return "PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE";
+		case PVRSRV_ERROR_NO_DEVICEDATA_FOUND:			return "PVRSRV_ERROR_NO_DEVICEDATA_FOUND";
+		case PVRSRV_ERROR_NO_DEVICENODE_FOUND:			return "PVRSRV_ERROR_NO_DEVICENODE_FOUND";
+		case PVRSRV_ERROR_NO_CLIENTNODE_FOUND:			return "PVRSRV_ERROR_NO_CLIENTNODE_FOUND";
+		case PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE:		return "PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE";
+
+		case PVRSRV_ERROR_UNABLE_TO_INIT_TASK:			return "PVRSRV_ERROR_UNABLE_TO_INIT_TASK";
+		case PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK:		return "PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK";
+		case PVRSRV_ERROR_UNABLE_TO_KILL_TASK:			return "PVRSRV_ERROR_UNABLE_TO_KILL_TASK";
+
+		case PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER:		return "PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER";
+		case PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER:		return "PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER";
+		case PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER:		return "PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER";
+
+		case PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT:			return "PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT";
+		case PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION:		return "PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION";
+
+		case PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE:	return "PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE";
+		case PVRSRV_ERROR_HANDLE_NOT_ALLOCATED:			return "PVRSRV_ERROR_HANDLE_NOT_ALLOCATED";
+		case PVRSRV_ERROR_HANDLE_TYPE_MISMATCH:			return "PVRSRV_ERROR_HANDLE_TYPE_MISMATCH";
+		case PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE:			return "PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE";
+		case PVRSRV_ERROR_HANDLE_NOT_SHAREABLE:			return "PVRSRV_ERROR_HANDLE_NOT_SHAREABLE";
+		case PVRSRV_ERROR_HANDLE_NOT_FOUND:				return "PVRSRV_ERROR_HANDLE_NOT_FOUND";
+		case PVRSRV_ERROR_INVALID_SUBHANDLE:			return "PVRSRV_ERROR_INVALID_SUBHANDLE";
+		case PVRSRV_ERROR_HANDLE_BATCH_IN_USE:			return "PVRSRV_ERROR_HANDLE_BATCH_IN_USE";
+		case PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE:	return "PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE";
+
+		case PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE:	return "PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE";
+		case PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED:return "PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED";
+
+		case PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE:	return "PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE";
+		case PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP:	return "PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP";
+
+		case PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE:	return "PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE";
+
+		case PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE:	return "PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE";
+		case PVRSRV_ERROR_INVALID_DEVICEID:				return "PVRSRV_ERROR_INVALID_DEVICEID";
+		case PVRSRV_ERROR_DEVICEID_NOT_FOUND:			return "PVRSRV_ERROR_DEVICEID_NOT_FOUND";
+
+		case PVRSRV_ERROR_MEMORY_TEST_FAILED:			return "PVRSRV_ERROR_MEMORY_TEST_FAILED";
+		case PVRSRV_ERROR_CPUPADDR_TEST_FAILED:			return "PVRSRV_ERROR_CPUPADDR_TEST_FAILED";
+		case PVRSRV_ERROR_COPY_TEST_FAILED:				return "PVRSRV_ERROR_COPY_TEST_FAILED";
+
+		case PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED:	return "PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED";
+
+		case PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK:		return "PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK";
+		case PVRSRV_ERROR_CLOCK_REQUEST_FAILED:			return "PVRSRV_ERROR_CLOCK_REQUEST_FAILED";
+		case PVRSRV_ERROR_DISABLE_CLOCK_FAILURE:		return "PVRSRV_ERROR_DISABLE_CLOCK_FAILURE";
+		case PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE:		return "PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE";
+		case PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE:	return "PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE";
+		case PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK:		return "PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK";
+		case PVRSRV_ERROR_UNABLE_TO_GET_CLOCK:			return "PVRSRV_ERROR_UNABLE_TO_GET_CLOCK";
+		case PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK:	return "PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK";
+		case PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK:	return "PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK";
+
+		case PVRSRV_ERROR_UNKNOWN_SGL_ERROR:			return "PVRSRV_ERROR_UNKNOWN_SGL_ERROR";
+	    case PVRSRV_ERROR_BAD_SYNC_STATE:               return "PVRSRV_ERROR_BAD_SYNC_STATE";
+
+	    case PVRSRV_ERROR_CACHE_INVALIDATE_FAILED:      return "PVRSRV_ERROR_CACHE_INVALIDATE_FAILED";
+
+		case PVRSRV_ERROR_FORCE_I32:					return "PVRSRV_ERROR_FORCE_I32";
+
+		default:
+			return "Unknown PVRSRV error number";
+	}
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __PVRSRV_ERRORS_H__ */
+
+/*****************************************************************************
+ End of file (pvrsrv_errors.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/include/servicesint.h b/drivers/gpu/pvr/services4/include/servicesint.h
new file mode 100644
index 0000000..ca93a12
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/servicesint.h
@@ -0,0 +1,616 @@
+/*************************************************************************/ /*!
+@Title          Services Internal Header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    services internal details
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "services.h"
+#include "sysinfo.h"
+
+#define HWREC_DEFAULT_TIMEOUT	(500)
+
+#define DRIVERNAME_MAXLENGTH	(100)
+
+/*
+	helper macros:
+*/
+#define	ALIGNSIZE(size, alignshift)	(((size) + ((1UL << (alignshift))-1)) & ~((1UL << (alignshift))-1))
+
+#ifndef MAX
+#define MAX(a,b) 					(((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) 					(((a) < (b)) ? (a) : (b))
+#endif
+
+/*
+	Note:
+	MAX_CLEANUP_TRYS is set to try and be around the frame rate
+	as for every try we will kick the uKernel which we want to avoid
+	doing too often (as we risk flooding the uKernel trace buffer
+	with requests and losing important information from before the
+	cleanup requests started).
+*/
+#define MAX_CLEANUP_TIME_US			(MAX_HW_TIME_US * 4)
+#define MAX_CLEANUP_TRYS			100
+#define MAX_CLEANUP_TIME_WAIT_US	(MAX_CLEANUP_TIME_US/MAX_CLEANUP_TRYS)
+
+typedef enum _PVRSRV_MEMTYPE_
+{
+	PVRSRV_MEMTYPE_UNKNOWN		= 0,
+	PVRSRV_MEMTYPE_DEVICE		= 1,
+	PVRSRV_MEMTYPE_DEVICECLASS	= 2,
+	PVRSRV_MEMTYPE_WRAPPED		= 3,
+	PVRSRV_MEMTYPE_MAPPED		= 4,
+	PVRSRV_MEMTYPE_ION		= 5,
+	PVRSRV_MEMTYPE_DMABUF		= 6,
+	PVRSRV_MEMTYPE_ALLOC		= 7,
+	PVRSRV_MEMTYPE_FREE	    	= 8
+} PVRSRV_MEMTYPE;
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+/* Threshold on number of latest operations to track*/
+#define MAX_MEM_TRACK_OPS 512
+typedef struct _PVRSRV_MEM_TRACK_INFO_
+{
+	IMG_DEV_VIRTADDR		sDevVAddr;
+	IMG_SIZE_T			uSize;
+	IMG_UINT32			ui32Pid;
+	IMG_UINT32			ui32RefCount;
+	PVRSRV_MEMTYPE		eOp;
+	IMG_UINT32			ui32TimeStampUSecs;
+	IMG_CHAR			asTaskName[128];
+	IMG_CHAR			heapId[128];
+	struct _PVRSRV_MEM_TRACK_INFO_ *next;
+	struct _PVRSRV_MEM_TRACK_INFO_ *prev;
+
+} PVRSRV_MEM_TRACK_INFO;
+#endif
+/*
+	Kernel Memory Information structure
+*/
+typedef struct _PVRSRV_KERNEL_MEM_INFO_
+{
+	/* Kernel Mode CPU Virtual address */
+	IMG_PVOID				pvLinAddrKM;
+
+	/* Device Virtual Address */
+	IMG_DEV_VIRTADDR		sDevVAddr;
+
+	/* allocation flags */
+	IMG_UINT32				ui32Flags;
+
+	/* Size of the allocated buffer in bytes */
+	IMG_SIZE_T				uAllocSize;
+
+	/* Internal implementation details. Do not use outside services code. */
+	PVRSRV_MEMBLK			sMemBlk;
+
+	/* Address of the backup buffer used in a save/restore of the surface */
+	IMG_PVOID				pvSysBackupBuffer;
+
+	/* refcount for allocation, wrapping and mapping */
+	IMG_UINT32				ui32RefCount;
+
+	/* Set when free call ocured and a mapping was still open */
+	IMG_BOOL				bPendingFree;
+
+
+#if defined(SUPPORT_MEMINFO_IDS)
+	#if !defined(USE_CODE)
+	/* Globally unique "stamp" for allocation (not re-used until wrap) */
+	IMG_UINT64				ui64Stamp;
+	#else /* !defined(USE_CODE) */
+	IMG_UINT32				dummy1;
+	IMG_UINT32				dummy2;
+	#endif /* !defined(USE_CODE) */
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
+
+	/* ptr to associated kernel sync info - NULL if no sync */
+	struct _PVRSRV_KERNEL_SYNC_INFO_	*psKernelSyncInfo;
+
+	IMG_HANDLE				hIonSyncInfo;
+
+#if defined(SUPPORT_DMABUF)
+	IMG_HANDLE				hDmaBufSyncInfo;
+#endif
+
+	PVRSRV_MEMTYPE				memType;
+
+    /*
+      To activate the "share mem workaround", add PVRSRV_MEM_XPROC to
+      the flags for the allocation.  This will cause the "map" API to
+      call use Alloc Device Mem but will share the underlying memory
+      block and sync data.
+    */
+	struct {
+        /* Record whether the workaround is active for this
+           allocation.  The rest of the fields in this struct are
+           undefined unless this is true */
+		IMG_BOOL bInUse;
+
+        /* Store the device cookie handle from the original
+           allocation, as it is not present on the "Map" API. */
+		IMG_HANDLE hDevCookieInt;
+
+        /* This is an index into a static array which store
+           information about the underlying allocation */
+		IMG_UINT32 ui32ShareIndex;
+
+        /* Original arguments as supplied to original
+           "PVRSRVAllocDeviceMem" call, such that a new call to this
+           function can be later constructed */
+		IMG_UINT32 ui32OrigReqAttribs;
+		IMG_UINT32 ui32OrigReqSize;
+		IMG_UINT32 ui32OrigReqAlignment;
+	} sShareMemWorkaround;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	IMG_CHAR heapId[128];
+#endif
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	IMG_UINT32 ui32TimeToDevMap;
+	IMG_UINT32 *pui32TimeToDevUnmap;	/* API user to provide space for storing "unmap" time */
+#endif
+} PVRSRV_KERNEL_MEM_INFO;
+
+
+/*
+	Kernel Sync Info structure
+*/
+typedef struct _PVRSRV_KERNEL_SYNC_INFO_
+{
+	/* kernel sync data */
+	PVRSRV_SYNC_DATA		*psSyncData;
+
+	/* Device accessible WriteOp Info */
+	IMG_DEV_VIRTADDR		sWriteOpsCompleteDevVAddr;
+
+	/* Device accessible ReadOp Info */
+	IMG_DEV_VIRTADDR		sReadOpsCompleteDevVAddr;
+
+	/* Device accessible ReadOp Info */
+	IMG_DEV_VIRTADDR		sReadOps2CompleteDevVAddr;
+
+	/* meminfo for sync data */
+	PVRSRV_KERNEL_MEM_INFO	*psSyncDataMemInfoKM;
+
+	/* Reference count for deferring destruction of syncinfo when it is shared */
+	/* NB: This is only done for devicemem.c (alloc/map/wrap etc), and
+	   not (presently) for deviceclass memory */
+	IMG_PVOID              pvRefCount;
+
+	/* Resman cleanup, for those created with explicit API */
+	IMG_HANDLE hResItem;
+
+	/* Unique ID of the sync object */
+	IMG_UINT32		ui32UID;
+
+#if defined(SUPPORT_DMABUF)
+	IMG_HANDLE		hFenceContext;
+#endif
+	/* Pointer for list manager */
+	struct _PVRSRV_KERNEL_SYNC_INFO_ *psNext;
+	struct _PVRSRV_KERNEL_SYNC_INFO_ **ppsThis;
+
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+#define PER_SYNC_HISTORY	10
+	IMG_UINT32		ui32OperationMask;
+	IMG_UINT32		aui32OpInfo[PER_SYNC_HISTORY];
+	IMG_UINT32		aui32ReadOpSample[PER_SYNC_HISTORY];
+	IMG_UINT32		aui32WriteOpSample[PER_SYNC_HISTORY];
+	IMG_UINT32		aui32ReadOp2Sample[PER_SYNC_HISTORY];
+	IMG_UINT32		ui32HistoryIndex;
+#endif
+
+} PVRSRV_KERNEL_SYNC_INFO;
+
+/*!
+ *****************************************************************************
+ *	This is a device addressable version of a pvrsrv_sync_oject
+ *	- any hw cmd may have an unlimited number of these
+ ****************************************************************************/
+typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_
+{
+	/* KEEP THESE 6 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
+	IMG_UINT32			ui32ReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	sReadOpsCompleteDevVAddr;
+	IMG_UINT32			ui32WriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	sWriteOpsCompleteDevVAddr;
+	IMG_UINT32			ui32ReadOps2PendingVal;
+	IMG_DEV_VIRTADDR	sReadOps2CompleteDevVAddr;
+} PVRSRV_DEVICE_SYNC_OBJECT;
+
+/*!
+ *****************************************************************************
+ *	encapsulates a single sync object
+ *	- any cmd may have an unlimited number of these
+ ****************************************************************************/
+typedef struct _PVRSRV_SYNC_OBJECT
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
+	IMG_UINT32				ui32WriteOpsPending;
+	IMG_UINT32				ui32ReadOpsPending;
+	IMG_UINT32				ui32ReadOps2Pending;
+
+}PVRSRV_SYNC_OBJECT, *PPVRSRV_SYNC_OBJECT;
+
+/*!
+ *****************************************************************************
+ * The `one size fits all' generic command.
+ ****************************************************************************/
+typedef struct _PVRSRV_COMMAND
+{
+	IMG_SIZE_T			uCmdSize;		/*!< total size of command */
+	IMG_UINT32			ui32DevIndex;		/*!< device type - 16bit enum (exported by system) */
+	IMG_UINT32			CommandType;		/*!< command type */
+	IMG_UINT32			ui32DstSyncCount;	/*!< number of dst sync objects */
+	IMG_UINT32			ui32SrcSyncCount;	/*!< number of src sync objects */
+	PVRSRV_SYNC_OBJECT	*psDstSync;			/*!< dst sync ptr list, allocated on
+                                       			back of this structure, i.e. is resident in Q */
+	PVRSRV_SYNC_OBJECT	*psSrcSync;			/*!< src sync ptr list, allocated on
+                                         		back of this structure, i.e. is resident in Q */
+	IMG_SIZE_T			uDataSize;		/*!< Size of Cmd Data Packet
+                                      			- only required in terms of allocating Q space */
+	IMG_UINT32			ui32ProcessID;		/*!< Process ID for debugging */
+	IMG_VOID			*pvData;			/*!< data to be passed to Cmd Handler function,
+                                         		allocated on back of this structure, i.e. is resident in Q */
+	PFN_QUEUE_COMMAND_COMPLETE  pfnCommandComplete;	/*!< Command complete callback */
+	IMG_HANDLE					hCallbackData;		/*!< Command complete callback data */
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	IMG_VOID			*pvCleanupFence;	/*!< Sync fence to 'put' after timeline inc() */
+	IMG_VOID			*pvTimeline;		/*!< Android sync timeline to inc() */
+#endif
+}PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+
+
+/*!
+ *****************************************************************************
+ * Circular command buffer structure forming the queue of pending commands.
+ *
+ * Queues are implemented as circular comamnd buffers (CCBs).
+ * The buffer is allocated as a specified size, plus the size of the largest supported command.
+ * The extra size allows commands to be added without worrying about wrapping around at the end.
+ *
+ * Commands are added to the CCB by client processes and consumed within
+ * kernel mode code running from within  an L/MISR typically.
+ *
+ * The process of adding a command to a queue is as follows:-
+ * 	- A `lock' is acquired to prevent other processes from adding commands to a queue
+ * 	- Data representing the command to be executed, along with it's PVRSRV_SYNC_INFO
+ * 	  dependencies is written to the buffer representing the queue at the queues
+ * 	  current WriteOffset.
+ * 	- The PVRSRV_SYNC_INFO that the command depends on are updated to reflect
+ * 	  the addition of the new command.
+ * 	- The WriteOffset is incremented by the size of the command added.
+ * 	- If the WriteOffset now lies beyound the declared buffer size, it is
+ * 	  reset to zero.
+ * 	- The semaphore is released.
+ *
+ *****************************************************************************/
+typedef struct _PVRSRV_QUEUE_INFO_
+{
+	IMG_VOID			*pvLinQueueKM;			/*!< Pointer to the command buffer in the kernel's
+												 address space */
+
+	IMG_VOID			*pvLinQueueUM;			/*!< Pointer to the command buffer in the user's
+												 address space */
+
+	volatile IMG_SIZE_T	uReadOffset;			/*!< Index into the buffer at which commands are being
+													 consumed */
+
+	volatile IMG_SIZE_T	uWriteOffset;			/*!< Index into the buffer at which commands are being
+													 added */
+
+	IMG_UINT32			*pui32KickerAddrKM;		/*!< kicker address in the kernel's
+												 address space*/
+
+	IMG_UINT32			*pui32KickerAddrUM;		/*!< kicker address in the user's
+												 address space */
+
+	IMG_SIZE_T			uQueueSize;				/*!< Size in bytes of the buffer - excluding the safety allocation */
+
+	IMG_UINT32			ui32ProcessID;			/*!< Process ID required by resource locking */
+
+	IMG_HANDLE			hMemBlock[2];
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	IMG_UINT32			ui32FenceValue;			/*!< 'Target' timeline value when fence signals */
+	IMG_VOID			*pvTimeline;			/*!< Android struct sync_timeline object */
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	IMG_UINT32			ui32FenceValue;			/*!< 'Target' timeline value when fence signals */
+	IMG_INT32			i32TimelineFd;			/*!< Fd for time line */
+#endif
+
+	struct _PVRSRV_QUEUE_INFO_ *psNextKM;		/*!< The next queue in the system */
+}PVRSRV_QUEUE_INFO;
+
+
+typedef struct _PVRSRV_HEAP_INFO_KM_
+{
+	IMG_UINT32			ui32HeapID;
+	IMG_DEV_VIRTADDR	sDevVAddrBase;
+
+	IMG_HANDLE 			hDevMemHeap;
+	IMG_UINT32			ui32HeapByteSize;
+	IMG_UINT32			ui32Attribs;
+	IMG_UINT32			ui32XTileStride;
+}PVRSRV_HEAP_INFO_KM;
+
+
+/*
+	Event Object information structure
+*/
+typedef struct _PVRSRV_EVENTOBJECT_KM_
+{
+	/* globally unique name of the event object */
+	IMG_CHAR	szName[EVENTOBJNAME_MAXLENGTH];
+	/* kernel specific handle for the event object */
+	IMG_HANDLE	hOSEventKM;
+
+} PVRSRV_EVENTOBJECT_KM;
+
+
+/*!
+ ******************************************************************************
+ * Structure to retrieve misc. information from services
+ *****************************************************************************/
+typedef struct _PVRSRV_MISC_INFO_KM_
+{
+	IMG_UINT32	ui32StateRequest;		/*!< requested State Flags */
+	IMG_UINT32	ui32StatePresent;		/*!< Present/Valid State Flags */
+
+	/*!< SOC Timer register */
+	IMG_VOID	*pvSOCTimerRegisterKM;
+	IMG_VOID	*pvSOCTimerRegisterUM;
+	IMG_HANDLE	hSOCTimerRegisterOSMemHandle;
+	IMG_HANDLE	hSOCTimerRegisterMappingInfo;
+
+	/*!< SOC Clock Gating registers */
+	IMG_VOID	*pvSOCClockGateRegs;
+	IMG_UINT32	ui32SOCClockGateRegsSize;
+
+	/* Memory Stats/DDK version string depending on ui32StateRequest flags */
+	IMG_CHAR	*pszMemoryStr;
+	IMG_UINT32	ui32MemoryStrLen;
+
+	/* global event object */
+	PVRSRV_EVENTOBJECT_KM	sGlobalEventObject;//FIXME: should be private to services
+	IMG_HANDLE				hOSGlobalEvent;
+
+	/* Note: add misc. items as required */
+	IMG_UINT32	aui32DDKVersion[4];
+
+	/*!< CPU cache flush controls: */
+	struct
+	{
+		/*!< Defer the CPU cache op to the next HW op to be submitted (else flush now) */
+		IMG_BOOL bDeferOp;
+
+		/*!< Type of cache operation to perform */
+		PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
+
+		/*!< Meminfo (or meminfo handle) to flush */
+		PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+		/*!< Offset in MemInfo to start cache op */
+		IMG_VOID *pvBaseVAddr;
+
+		/*!< Length of range to perform cache op  */
+		IMG_UINT32	ui32Length;
+	} sCacheOpCtl;
+
+	/*!< Meminfo refcount controls: */
+	struct
+	{
+		/*!< Meminfo (or meminfo handle) to get refcount for */
+		PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+		/*!< Resulting refcount */
+		IMG_UINT32 ui32RefCount;
+	} sGetRefCountCtl;
+} PVRSRV_MISC_INFO_KM;
+
+
+/* insert command function pointer */
+typedef PVRSRV_ERROR (*PFN_INSERT_CMD) (PVRSRV_QUEUE_INFO*,
+										PVRSRV_COMMAND**,
+										IMG_UINT32,
+										IMG_UINT16,
+										IMG_UINT32,
+										PVRSRV_KERNEL_SYNC_INFO*[],
+										IMG_UINT32,
+										PVRSRV_KERNEL_SYNC_INFO*[],
+										IMG_UINT32);
+/* submit command function pointer */
+typedef PVRSRV_ERROR (*PFN_SUBMIT_CMD) (PVRSRV_QUEUE_INFO*, PVRSRV_COMMAND*, IMG_BOOL);
+
+
+/***********************************************************************
+	Device Class Structures
+***********************************************************************/
+
+/*
+	Generic Device Class Buffer
+	- details common between DC and BC
+*/
+typedef struct PVRSRV_DEVICECLASS_BUFFER_TAG
+{
+	PFN_GET_BUFFER_ADDR		pfnGetBufferAddr;
+	IMG_HANDLE				hDevMemContext;
+	IMG_HANDLE				hExtDevice;
+	IMG_HANDLE				hExtBuffer;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	IMG_UINT32				ui32MemMapRefCount;
+} PVRSRV_DEVICECLASS_BUFFER;
+
+
+/*
+	Common Device Class client services information structure
+*/
+typedef struct PVRSRV_CLIENT_DEVICECLASS_INFO_TAG
+{
+	IMG_HANDLE hDeviceKM;
+	IMG_HANDLE	hServices;
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	IMG_INT32	i32TimelineFd;
+	IMG_INT32	i32Unused;
+#endif
+} PVRSRV_CLIENT_DEVICECLASS_INFO;
+
+
+typedef enum
+{
+	PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR,
+	PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER,
+	PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL,
+}
+PVRSRV_FREE_CALLBACK_ORIGIN;
+
+
+IMG_IMPORT
+PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+                                   IMG_UINT32 ui32Param,
+                                   PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin);
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVQueueCommand(IMG_HANDLE hQueueInfo,
+								PVRSRV_COMMAND *psCommand);
+
+
+/*!
+ * *****************************************************************************
+ * @Description Allocates system memory on behalf of a userspace process that is
+ * 		  addressable by the kernel; suitable for mapping into the current
+ *        user space process; suitable for mapping into other userspace
+ *        processes and it is possible to entirely disassociate the system
+ *        memory from the current userspace process via a call to
+ *        PVRSRVDissociateSharedSysMemoryKM.
+ *
+ * @Input psConnection
+ * @Input ui32Flags
+ * @Input ui32Size
+ * @Output ppsClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVAllocSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+						IMG_UINT32 ui32Flags,
+						IMG_SIZE_T uSize,
+						PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+/*!
+ * *****************************************************************************
+ * @Description Frees memory allocated via PVRSRVAllocSharedMemory (Note you must
+ *        be sure any additional kernel references you created have been
+ *        removed before freeing the memory)
+ *
+ * @Input psConnection
+ * @Input psClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVFreeSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+					   PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+/*!
+ * *****************************************************************************
+ * @Description Removes any userspace reference to the shared system memory, except
+ *        that the memory will remain registered with the services resource
+ *        manager so if the process dies/exits the actuall shared memory will
+ *        still be freed.
+ *        If you need to move ownership of shared memory from userspace
+ *        to kernel space then before unrefing a shared piece of memory you can
+ *        take a copy of psClientMemInfo->hKernelMemInfo; call
+ *        PVRSRVUnrefSharedSysMem; then use some mechanism (specialised bridge
+ *        function) to request that the kernel remove any resource manager
+ *        reference to the shared memory and assume responsaility for the meminfo
+ *        in one atomic operation. (Note to aid with such a kernel space bridge
+ *        function see PVRSRVDissociateSharedSysMemoryKM)
+ *
+ * @Input psConnection
+ * @Input psClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVUnrefSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+                        PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+/*!
+ * *****************************************************************************
+ * @Description For shared system or device memory that is owned by the kernel, you can
+ *              use this function to map the underlying memory into a client using a
+ *              handle for the KernelMemInfo.
+ *
+ * @Input psConnection
+ * @Input hKernelMemInfo
+ * @Output ppsClientMemInfo
+ *
+ * @Return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVMapMemInfoMem(const PVRSRV_CONNECTION *psConnection,
+                    IMG_HANDLE hKernelMemInfo,
+                    PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+#if defined(MEM_TRACK_INFO_DEBUG)
+IMG_IMPORT IMG_VOID PVRSRVPrintMemTrackInfo(IMG_UINT32 ui32FaultAddr);
+IMG_IMPORT IMG_VOID PVRSRVAddMemTrackInfo(PVRSRV_MEM_TRACK_INFO *psMemTrackInfo);
+IMG_IMPORT IMG_VOID PVRSRVFreeMemOps(IMG_VOID);
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __SERVICESINT_H__ */
+
+/*****************************************************************************
+ End of file (servicesint.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/include/sgx_bridge.h b/drivers/gpu/pvr/services4/include/sgx_bridge.h
new file mode 100644
index 0000000..93b38f9
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/sgx_bridge.h
@@ -0,0 +1,577 @@
+/*************************************************************************/ /*!
+@Title          SGX Bridge Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the sgx Brdige code
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__SGX_BRIDGE_H__)
+#define __SGX_BRIDGE_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "pvr_bridge.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+/* 
+ * Bridge Cmd Ids
+ */
+
+/* *REMEMBER* to update PVRSRV_BRIDGE_LAST_SGX_CMD if you add/remove a command! 
+ * Also you need to ensure all PVRSRV_BRIDGE_SGX_CMD_BASE+ offsets are sequential!
+ */
+
+#define PVRSRV_BRIDGE_SGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+#define PVRSRV_BRIDGE_SGX_GETCLIENTINFO			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+0)
+#define PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+1)
+#define PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+2)
+#define PVRSRV_BRIDGE_SGX_DOKICK				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+3)
+#define PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+4)
+#define PVRSRV_BRIDGE_SGX_READREGISTRYDWORD		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+5)
+
+#define PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE   PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+9)
+
+#if defined(TRANSFER_QUEUE)
+#define PVRSRV_BRIDGE_SGX_SUBMITTRANSFER			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+13)
+#endif
+#define PVRSRV_BRIDGE_SGX_GETMISCINFO				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+14)
+#define PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+15)
+#define PVRSRV_BRIDGE_SGX_DEVINITPART2				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+16)
+
+#define PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+17)
+#define PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+18)
+#define PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+19)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+20)
+#define PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+21)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+22)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_BRIDGE_SGX_SUBMIT2D					PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+23)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+24)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+25)
+#endif
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+26)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+27)
+
+#define PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#define PVRSRV_BRIDGE_SGX_READ_HWPERF_CB			PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+29)
+#define PVRSRV_BRIDGE_SGX_SET_RENDER_CONTEXT_PRIORITY      PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+30)
+#define PVRSRV_BRIDGE_SGX_SET_TRANSFER_CONTEXT_PRIORITY      PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+31)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY		PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+32)
+#define PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+33)
+#define PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+34)
+#define PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS	PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+#define PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB				PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+36)
+#define PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM					PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+37)
+#endif
+
+
+
+/* *REMEMBER* to update PVRSRV_BRIDGE_LAST_SGX_CMD if you add/remove a command! 
+ * You need to ensure all PVRSRV_BRIDGE_SGX_CMD_BASE+ offsets are sequential!
+ */
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+37)
+
+/*****************************************************************************
+ * Input structures for IOCTL/DRVESC 
+ *****************************************************************************/
+
+/*!
+ *****************************************************************************
+ *	`bridge in' SGX Get Phys Page Addr
+ *****************************************************************************/ 
+typedef struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR
+{
+	IMG_HANDLE hDevMemHeap;
+	IMG_DEV_VIRTADDR sDevVAddr;
+}PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR;
+
+/*!
+ *****************************************************************************
+ *	`bridge out' SGX Get Phys Page Addr
+ *****************************************************************************/ 
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR
+{
+	PVRSRV_ERROR		eError;
+	IMG_DEV_PHYADDR		DevPAddr;
+	IMG_CPU_PHYADDR		CpuPAddr;
+}PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' set transfer context priority
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY_TAG
+ {
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hHWTransferContext;
+	IMG_UINT32			ui32Priority;
+	IMG_UINT32			ui32OffsetOfPriorityField;
+}PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' set render context priority
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hHWRenderContext;
+	IMG_UINT32			ui32Priority;
+	IMG_UINT32			ui32OffsetOfPriorityField;
+}PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' Get Client Info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GETCLIENTINFO_TAG
+{
+	IMG_HANDLE			hDevCookie;
+}PVRSRV_BRIDGE_IN_GETCLIENTINFO;
+
+/*!
+ *****************************************************************************
+ *	`bridge out' Get internal device info
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO_TAG
+{
+	SGX_INTERNAL_DEVINFO	sSGXInternalDevInfo;
+	PVRSRV_ERROR			eError;
+}PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' Get internal device info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO_TAG
+{
+	IMG_HANDLE			hDevCookie;
+}PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO;
+
+/*!
+ *****************************************************************************
+ *	`bridge out' Get Client Info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO_TAG
+{
+	SGX_CLIENT_INFO		sClientInfo;
+	PVRSRV_ERROR		eError;
+}PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' Release Client Info
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG
+{
+	IMG_HANDLE		hDevCookie;
+}PVRSRV_BRIDGE_IN_RELEASECLIENTINFO;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' Pdump ISP mem Pol
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL_TAG
+{
+	IMG_HANDLE		hDevCookie;
+}PVRSRV_BRIDGE_IN_ISPBREAKPOLL;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' KickTA
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_DOKICK_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	SGX_CCB_KICK		sCCBKick;
+}PVRSRV_BRIDGE_IN_DOKICK;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' SGXScheduleProcessQueues
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES_TAG
+{
+	IMG_HANDLE		hDevCookie;
+}PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES;
+
+
+#if defined(TRANSFER_QUEUE)
+/*!
+ *****************************************************************************
+ *	`bridge in' SubmitTransfer
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SUBMITTRANSFER_TAG
+{
+	IMG_HANDLE					hDevCookie;
+	PVRSRV_TRANSFER_SGX_KICK	sKick;
+}PVRSRV_BRIDGE_IN_SUBMITTRANSFER;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+/*!
+ *****************************************************************************
+ *	`bridge in' Submit2D
+ *****************************************************************************/ 
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SUBMIT2D_TAG
+{
+	IMG_UINT32				ui32BridgeFlags; /* Must be first member of structure */
+	IMG_HANDLE				hDevCookie;
+	PVRSRV_2D_SGX_KICK 		sKick;
+} PVRSRV_BRIDGE_IN_SUBMIT2D;
+#endif
+#endif
+
+/*!
+ *****************************************************************************
+ *	`bridge in' ReadRegistryString
+ *****************************************************************************/ 
+typedef struct PVRSRV_BRIDGE_IN_READREGDWORD_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_PCHAR			pszKey;
+    	IMG_PCHAR			pszValue;
+}PVRSRV_BRIDGE_IN_READREGDWORD;
+
+/*!
+ *****************************************************************************
+ *	`bridge out' ReadRegistryString
+ *****************************************************************************/ 
+typedef struct PVRSRV_BRIDGE_OUT_READREGDWORD_TAG
+{
+	PVRSRV_ERROR	eError;
+	IMG_UINT32	ui32Data;
+}PVRSRV_BRIDGE_OUT_READREGDWORD;
+
+
+/*!
+ *****************************************************************************
+ *	`bridge in' SGXGetMiscInfo
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hMiscInfo;
+}PVRSRV_BRIDGE_IN_SGXGETMISCINFO;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' SGXGetInfoForSrvInit
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT_TAG
+{
+	IMG_HANDLE			hDevCookie;
+}PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT;
+
+/*!
+ *****************************************************************************
+ *	`bridge out' SGXGetInfoForSrvInit
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT_TAG
+{
+	PVRSRV_ERROR				eError;
+	SGX_BRIDGE_INFO_FOR_SRVINIT	sInitInfo;
+}PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' SGXDevInitPart2
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGXDEVINITPART2_TAG
+{
+	IMG_HANDLE              hDevCookie;
+	SGX_BRIDGE_INIT_INFO	sInitInfo;
+}PVRSRV_BRIDGE_IN_SGXDEVINITPART2;
+
+/*!
+ *****************************************************************************
+ *	`bridge out' SGXDevInitPart2
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_SGXDEVINITPART2_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_UINT32			ui32KMBuildOptions;
+}PVRSRV_BRIDGE_OUT_SGXDEVINITPART2;
+
+/*!
+ *****************************************************************************
+ *	`bridge in' 2D query blits complete
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hKernSyncInfo;
+	IMG_BOOL			bWaitForComplete;
+}PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE;
+
+
+#define PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS 10
+
+typedef struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC_TAG
+{
+	IMG_HANDLE hDevCookie;
+	IMG_BOOL   bLockOnFailure;
+	IMG_UINT32 ui32TotalPBSize;
+}PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC_TAG
+{
+	IMG_HANDLE hKernelMemInfo;
+	IMG_HANDLE hSharedPBDesc;
+	IMG_HANDLE hSharedPBDescKernelMemInfoHandle;
+	IMG_HANDLE hHWPBDescKernelMemInfoHandle;
+	IMG_HANDLE hBlockKernelMemInfoHandle;
+	IMG_HANDLE hHWBlockKernelMemInfoHandle;
+	IMG_HANDLE ahSharedPBDescSubKernelMemInfoHandles[PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+	IMG_UINT32 ui32SharedPBDescSubKernelMemInfoHandlesCount;
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC_TAG
+{
+	IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC_TAG
+{
+	PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC_TAG
+{
+	IMG_UINT32 ui32TotalPBSize;
+	IMG_HANDLE hDevCookie;
+	IMG_HANDLE hSharedPBDescKernelMemInfo;
+	IMG_HANDLE hHWPBDescKernelMemInfo;
+	IMG_HANDLE hBlockKernelMemInfo;
+	IMG_HANDLE hHWBlockKernelMemInfo;
+	IMG_HANDLE *phKernelMemInfoHandles;
+	IMG_UINT32 ui32KernelMemInfoHandlesCount;
+	IMG_DEV_VIRTADDR sHWPBDescDevVAddr;
+}PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC;
+
+
+#ifdef	PDUMP
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY_TAG
+{
+	IMG_HANDLE 				hBufferArray;
+	IMG_UINT32				ui32BufferArrayLength;
+	IMG_BOOL				bDumpPolls;
+} PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hDevMemContext;
+	IMG_UINT32			ui32DumpFrameNum;
+	IMG_BOOL			bLastFrame;
+	IMG_HANDLE			hRegisters;
+	IMG_UINT32			ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMPCOUNTER_REGISTERS_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_UINT32			ui32DumpFrameNum;
+	IMG_BOOL			bLastFrame;
+	IMG_HANDLE			hRegisters;
+	IMG_UINT32			ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_UINT32			ui32DumpFrameNum;
+	IMG_UINT32			ui32TAKickCount;
+	IMG_BOOL			bLastFrame;
+	IMG_HANDLE			hRegisters;
+	IMG_UINT32			ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hDevMemContext;
+	IMG_CHAR			szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+	IMG_UINT32			ui32FileOffset;
+	IMG_UINT32			ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_CHAR			szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+	IMG_UINT32			ui32FileOffset;
+	IMG_DEV_VIRTADDR	 	sDevVAddr;
+	IMG_UINT32			ui32Size;
+	IMG_HANDLE			hDevMemContext;
+	IMG_UINT32			ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM;
+
+#endif
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			pHWRenderContextCpuVAddr;
+	IMG_UINT32			ui32HWRenderContextSize;
+	IMG_UINT32			ui32OffsetToPDDevPAddr;
+	IMG_HANDLE			hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_DEV_VIRTADDR	sHWRenderContextDevVAddr;
+	IMG_HANDLE			hHWRenderContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT_TAG
+{
+	IMG_BOOL			bForceCleanup;
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hHWRenderContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			pHWTransferContextCpuVAddr;
+	IMG_UINT32			ui32HWTransferContextSize;
+	IMG_UINT32			ui32OffsetToPDDevPAddr;
+	IMG_HANDLE			hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_DEV_VIRTADDR	sHWTransferContextDevVAddr;
+	IMG_HANDLE			hHWTransferContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+	IMG_BOOL			bForceCleanup;
+	IMG_HANDLE			hDevCookie;
+	IMG_HANDLE			hHWTransferContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_DEV_VIRTADDR	sHWRTDataSetDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET;
+
+/*!
+ *****************************************************************************
+ *	SGX 2D specific defines
+ *****************************************************************************/ 
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
+	IMG_HANDLE hDevCookie;
+    IMG_HANDLE hHW2DContextCpuVAddr;
+    IMG_UINT32       ui32HW2DContextSize;
+    IMG_UINT32       ui32OffsetToPDDevPAddr;
+    IMG_HANDLE       hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hHW2DContext;
+    IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT_TAG
+{
+	IMG_UINT32 ui32BridgeFlags; /* Must be first member of structure */
+	IMG_BOOL   bForceCleanup;
+	IMG_HANDLE hDevCookie;
+	IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT;
+
+#define	SGX2D_MAX_BLT_CMD_SIZ		256	/* Maximum size of a blit command, in bytes */
+#endif /* SGX_FEATURE_2D_HARDWARE */
+
+
+/*!
+ *****************************************************************************
+ *	`bridge in' SGXReadHWPerfCB
+ *****************************************************************************/
+typedef struct IMG_COMPAT PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB_TAG
+{
+	IMG_HANDLE			hDevCookie;
+	IMG_UINT32			ui32ArraySize;
+	IMG_HANDLE			hHWPerfCBData;		/* PVRSRV_SGX_HWPERF_CB_ENTRY* */
+} PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB;
+
+/*!
+ *****************************************************************************
+ *	`bridge out' SGXReadHWPerfCB
+ *****************************************************************************/
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB_TAG
+{
+	PVRSRV_ERROR		eError;
+	IMG_UINT32			ui32DataCount;
+	IMG_UINT32			ui32ClockSpeed;
+	IMG_UINT32			ui32HostTimeStamp;
+} PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __SGX_BRIDGE_H__ */
+
diff --git a/drivers/gpu/pvr/services4/include/sgx_mkif_km.h b/drivers/gpu/pvr/services4/include/sgx_mkif_km.h
new file mode 100644
index 0000000..f67ceaa
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/sgx_mkif_km.h
@@ -0,0 +1,476 @@
+/*************************************************************************/ /*!
+@Title          SGX microkernel interface structures used by srvkm
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    SGX microkernel interface structures used by srvkm
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined (__SGX_MKIF_KM_H__)
+#define __SGX_MKIF_KM_H__
+
+#include "img_types.h"
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+
+#if !defined (SGX_MP_CORE_SELECT)
+/* MP register control macros */
+#if defined(SGX_FEATURE_MP)
+	#define SGX_REG_BANK_SHIFT 			(14)
+	#define SGX_REG_BANK_SIZE 			(1 << SGX_REG_BANK_SHIFT)
+	#define SGX_REG_BANK_BASE_INDEX		(2)
+	#define	SGX_REG_BANK_MASTER_INDEX	(1)
+	#define SGX_MP_CORE_SELECT(x,i) 	(x + ((i + SGX_REG_BANK_BASE_INDEX) * SGX_REG_BANK_SIZE))
+	#define SGX_MP_MASTER_SELECT(x) 	(x + (SGX_REG_BANK_MASTER_INDEX * SGX_REG_BANK_SIZE))
+#else
+	#define SGX_MP_CORE_SELECT(x,i) 	(x)
+#endif /* SGX_FEATURE_MP */
+#endif
+
+
+/*!
+ ******************************************************************************
+ * CCB command structure for SGX
+ *****************************************************************************/
+typedef struct _SGXMKIF_COMMAND_
+{
+	IMG_UINT32				ui32ServiceAddress;		/*!< address of the USE command handler */
+	IMG_UINT32				ui32CacheControl;		/*!< See SGXMKIF_CC_INVAL_* */
+	IMG_UINT32				ui32Data[6];			/*!< array of other command control words */
+} SGXMKIF_COMMAND;
+
+
+/*!
+ ******************************************************************************
+ * CCB array of commands for SGX
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_KERNEL_CCB_
+{
+	SGXMKIF_COMMAND		asCommands[256];		/*!< array of commands */
+} PVRSRV_SGX_KERNEL_CCB;
+
+
+/*!
+ ******************************************************************************
+ * CCB control for SGX
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_CCB_CTL_
+{
+	IMG_UINT32				ui32WriteOffset;		/*!< write offset into array of commands (MUST be aligned to 16 bytes!) */
+	IMG_UINT32				ui32ReadOffset;			/*!< read offset into array of commands */
+} PVRSRV_SGX_CCB_CTL;
+
+
+/*!
+ *****************************************************************************
+ * Control data for SGX
+ *****************************************************************************/
+typedef struct _SGXMKIF_HOST_CTL_
+{
+#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
+	IMG_UINT32				ui32BreakpointDisable;
+	IMG_UINT32				ui32Continue;
+#endif
+
+	volatile IMG_UINT32		ui32InitStatus;				/*!< Microkernel Initialisation status */
+	volatile IMG_UINT32		ui32PowerStatus;			/*!< Microkernel Power Management status */
+	volatile IMG_UINT32		ui32CleanupStatus;			/*!< Microkernel Resource Management status */
+#if defined(FIX_HW_BRN_28889)
+	volatile IMG_UINT32		ui32InvalStatus;			/*!< Microkernel BIF Cache Invalidate status */
+#endif
+#if defined(SUPPORT_HW_RECOVERY)
+	IMG_UINT32				ui32uKernelDetectedLockups;	/*!< counter relating to the number of lockups the uKernel has detected */
+	IMG_UINT32				ui32HostDetectedLockups;	/*!< counter relating to the number of lockups the host has detected */
+	IMG_UINT32				ui32HWRecoverySampleRate;	/*!< SGX lockup detection rate (in multiples of the timer period) */
+#endif /* SUPPORT_HW_RECOVERY*/
+	IMG_UINT32				ui32uKernelTimerClock;		/*!< SGX ukernel timer period (in clocks) */
+	IMG_UINT32				ui32ActivePowManSampleRate;	/*!< SGX Active Power latency period (in multiples of the timer period) */
+	IMG_UINT32				ui32InterruptFlags; 		/*!< Interrupt flags - PVRSRV_USSE_EDM_INTERRUPT_xxx */
+	IMG_UINT32				ui32InterruptClearFlags; 	/*!< Interrupt clear flags - PVRSRV_USSE_EDM_INTERRUPT_xxx */
+	IMG_UINT32				ui32BPSetClearSignal;		/*!< Breakpoint set/cear signal */
+
+	IMG_UINT32				ui32NumActivePowerEvents;	/*!< counter for the number of active power events */
+
+	IMG_UINT32				ui32TimeWraps;				/*!< to count time wraps in the Timer task*/
+	IMG_UINT32				ui32HostClock;				/*!< Host clock value at microkernel power-up time */
+	IMG_UINT32				ui32AssertFail;				/*!< Microkernel assert failure code */
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+	IMG_UINT32				aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];	/*!< Specifies the HW's active group selectors */
+	IMG_UINT32				aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];	/*!< Specifies the HW's active bit selectors */
+	IMG_UINT32				ui32PerfCounterBitSelect;						/*!< Specifies the HW's counter bit selectors */
+	IMG_UINT32				ui32PerfSumMux;									/*!< Specifies the HW's sum_mux selectors */
+#else
+	IMG_UINT32				ui32PerfGroup;									/*!< Specifies the HW's active group */
+#endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
+
+	IMG_UINT32				ui32OpenCLDelayCount;			/* Counter to keep track OpenCL task completion time in units of regular task time out events */
+	IMG_UINT32				ui32InterruptCount;
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	volatile IMG_UINT32		ui32SystraceIndex;			/*!< Current index for systrace */
+	volatile IMG_UINT32		ui32SGXPoweredOn;			/*!< if SGX is powered on */
+	volatile IMG_UINT32		ui32TicksAtPowerUp;		/*!< if SGX is powered on */
+#endif
+} SGXMKIF_HOST_CTL;
+
+/*
+ * TA queue Kick flags
+ */
+/* Set in DoKickKM to indicate the command is ready to be processed */
+#define	SGXMKIF_CMDTA_CTRLFLAGS_READY			0x00000001
+/*!
+ ******************************************************************************
+ * Shared TA command structure.
+ * This structure is part of the TA command structure proper (SGXMKIF_CMDTA),
+ * and is accessed from the kernel part of the driver and the microkernel.
+ * There shouldn't be a need to access it from user space.
+ *****************************************************************************/
+typedef struct _SGXMKIF_CMDTA_SHARED_
+{
+	IMG_UINT32			ui32CtrlFlags;
+	
+	IMG_UINT32			ui32NumTAStatusVals;
+	IMG_UINT32			ui32Num3DStatusVals;
+
+	/* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
+	IMG_UINT32			ui32TATQSyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTATQSyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32			ui32TATQSyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTATQSyncReadOpsCompleteDevVAddr;
+
+	/* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
+	IMG_UINT32			ui323DTQSyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DTQSyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32			ui323DTQSyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DTQSyncReadOpsCompleteDevVAddr;
+
+	/* sync criteria used for TA/3D dependency synchronisation */
+	PVRSRV_DEVICE_SYNC_OBJECT	sTA3DDependency;
+
+	/* source dependency details */
+	IMG_UINT32			ui32NumSrcSyncs;
+	PVRSRV_DEVICE_SYNC_OBJECT	asSrcSyncs[SGX_MAX_SRC_SYNCS_TA];
+
+	CTL_STATUS			sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+	CTL_STATUS			sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+} SGXMKIF_CMDTA_SHARED;
+
+/*
+ * Services internal TQ limits
+ */
+#define SGXTQ_MAX_STATUS						SGX_MAX_TRANSFER_STATUS_VALS + 2
+
+/*
+ * Transfer queue Kick flags
+ */
+/* if set the uKernel won't update the sync objects on completion*/
+#define SGXMKIF_TQFLAGS_NOSYNCUPDATE			0x00000001
+/* if set the kernel won't advance the pending values*/
+#define SGXMKIF_TQFLAGS_KEEPPENDING				0x00000002
+/* in services equivalent for the same client flags*/
+#define SGXMKIF_TQFLAGS_TATQ_SYNC				0x00000004
+#define SGXMKIF_TQFLAGS_3DTQ_SYNC				0x00000008
+#if defined(SGX_FEATURE_FAST_RENDER_CONTEXT_SWITCH)
+#define SGXMKIF_TQFLAGS_CTXSWITCH				0x00000010
+#endif
+/* if set uKernel only updates syncobjects / status values*/
+#define SGXMKIF_TQFLAGS_DUMMYTRANSFER			0x00000020
+
+/*!
+ ******************************************************************************
+ * Shared Transfer Queue command structure.
+ * This structure is placed at the start of the TQ command structure proper
+ * (SGXMKIF_TRANSFERCMD), and is accessed from the kernel part of the driver
+ * and the microkernel.
+ *****************************************************************************/
+typedef struct _SGXMKIF_TRANSFERCMD_SHARED_
+{
+	/* need to be able to check read and write ops on src, and update reads */
+
+ 	IMG_UINT32			ui32NumSrcSyncs;
+ 	PVRSRV_DEVICE_SYNC_OBJECT	asSrcSyncs[SGX_MAX_SRC_SYNCS_TQ];
+	/* need to be able to check reads and writes on dest, and update writes */
+
+ 	IMG_UINT32			ui32NumDstSyncs;
+ 	PVRSRV_DEVICE_SYNC_OBJECT	asDstSyncs[SGX_MAX_DST_SYNCS_TQ];	
+	/* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
+	IMG_UINT32		ui32TASyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTASyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32		ui32TASyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	sTASyncReadOpsCompleteDevVAddr;
+
+	/* KEEP THESE 4 VARIABLES TOGETHER FOR UKERNEL BLOCK LOAD */
+	IMG_UINT32		ui323DSyncWriteOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DSyncWriteOpsCompleteDevVAddr;
+	IMG_UINT32		ui323DSyncReadOpsPendingVal;
+	IMG_DEV_VIRTADDR	s3DSyncReadOpsCompleteDevVAddr;
+
+	IMG_UINT32 		ui32NumStatusVals;
+	CTL_STATUS  	sCtlStatusInfo[SGXTQ_MAX_STATUS];
+} SGXMKIF_TRANSFERCMD_SHARED, *PSGXMKIF_TRANSFERCMD_SHARED;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGXMKIF_2DCMD_SHARED_ {
+	/* need to be able to check read and write ops on src, and update reads */
+	IMG_UINT32			ui32NumSrcSync;
+	PVRSRV_DEVICE_SYNC_OBJECT	sSrcSyncData[SGX_MAX_2D_SRC_SYNC_OPS];
+
+	/* need to be able to check reads and writes on dest, and update writes */
+	PVRSRV_DEVICE_SYNC_OBJECT	sDstSyncData;
+
+	/* need to be able to check reads and writes on TA ops, and update writes */
+	PVRSRV_DEVICE_SYNC_OBJECT	sTASyncData;
+
+	/* need to be able to check reads and writes on 2D ops, and update writes */
+	PVRSRV_DEVICE_SYNC_OBJECT	s3DSyncData;
+
+	IMG_UINT32 		ui32NumStatusVals;
+	CTL_STATUS  	sCtlStatusInfo[SGXTQ_MAX_STATUS];
+} SGXMKIF_2DCMD_SHARED, *PSGXMKIF_2DCMD_SHARED;
+#endif /* SGX_FEATURE_2D_HARDWARE */
+
+
+typedef struct _SGXMKIF_HWDEVICE_SYNC_LIST_
+{
+	IMG_DEV_VIRTADDR	sAccessDevAddr;
+	IMG_UINT32			ui32NumSyncObjects;
+	/* Must be the last variable in the structure */
+	PVRSRV_DEVICE_SYNC_OBJECT	asSyncData[1];
+} SGXMKIF_HWDEVICE_SYNC_LIST, *PSGXMKIF_HWDEVICE_SYNC_LIST;
+
+
+/*!
+ *****************************************************************************
+ * Microkernel initialisation status
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_INIT_COMPLETE			(1UL << 0)	/*!< ukernel initialisation complete */
+
+/*!
+ *****************************************************************************
+ * Microkernel power status definitions
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE				(1UL << 2)	/*!< Signal from ukernel->Host indicating SGX is idle */
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE			(1UL << 3)	/*!< Signal from ukernel->Host indicating SGX can be powered down */
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE	(1UL << 4)	/*!< Signal from ukernel->Host indicating there is work to be done immediately */
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK						(1UL << 5)	/*!< Signal from ukernel->Host indicating nothing to do */
+
+/*!
+ *****************************************************************************
+ * EDM interrupt defines
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR			(1UL << 0)	/*!< EDM requesting hardware recovery */
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER	(1UL << 1)	/*!< EDM requesting to be powered down */
+#define PVRSRV_USSE_EDM_INTERRUPT_IDLE			(1UL << 2)	/*!< EDM indicating SGX idle */
+
+/*!
+ *****************************************************************************
+ * EDM Resource management defines
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE 	(1UL << 0)	/*!< Signal from EDM->Host indicating clean-up request completion */
+#define PVRSRV_USSE_EDM_CLEANUPCMD_BUSY		 	(1UL << 1)	/*!< Signal from EDM->Host indicating clean-up is blocked as the resource is busy */
+#define PVRSRV_USSE_EDM_CLEANUPCMD_DONE		 	(1UL << 2)	/*!< Signal from EDM->Host indicating clean-up has been done */
+
+#if defined(FIX_HW_BRN_28889)
+/*!
+ *****************************************************************************
+ * EDM BIF Cache Invalidate defines
+ *****************************************************************************/
+#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE 		(1UL << 0)	/*!< Signal from EDM->Host indicating the BIF invalidate has started */
+#endif
+
+/*!
+ ****************************************************************************
+ * EDM / uKernel Get misc info defines
+ ****************************************************************************
+ */
+#define PVRSRV_USSE_MISCINFO_READY		0x1UL
+#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES	0x2UL	/*!< If set, getmiscinfo ukernel func returns structure sizes */
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+#define PVRSRV_USSE_MISCINFO_MEMREAD			0x4UL	/*!< If set, getmiscinfo ukernel func reads arbitrary device mem */
+#define PVRSRV_USSE_MISCINFO_MEMWRITE			0x8UL	/*!< If set, getmiscinfo ukernel func writes arbitrary device mem */
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL		0x1UL << 31	/* If set, ukernel was unable to read from the mem context */
+#endif
+#endif
+
+
+/* Cleanup command control word */
+#define	PVRSRV_CLEANUPCMD_RT		0x1U
+#define	PVRSRV_CLEANUPCMD_RC		0x2U
+#define	PVRSRV_CLEANUPCMD_TC		0x3U
+#define	PVRSRV_CLEANUPCMD_2DC		0x4U
+#define	PVRSRV_CLEANUPCMD_PB		0x5U
+
+/* Power command control word */
+#define PVRSRV_POWERCMD_POWEROFF	0x1U
+#define PVRSRV_POWERCMD_IDLE		0x2U
+#define PVRSRV_POWERCMD_RESUME		0x3U
+
+/* Context suspend command control word */
+#define PVRSRV_CTXSUSPCMD_SUSPEND	0x1U
+#define PVRSRV_CTXSUSPCMD_RESUME	0x2U
+
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define SGX_BIF_DIR_LIST_INDEX_EDM	(SGX_FEATURE_BIF_NUM_DIRLISTS - 1)
+#else
+#define SGX_BIF_DIR_LIST_INDEX_EDM	(0)
+#endif
+
+/*!
+ ******************************************************************************
+ * microkernel cache control requests
+ ******************************************************************************/
+#define	SGXMKIF_CC_INVAL_BIF_PT	0x1
+#define	SGXMKIF_CC_INVAL_BIF_PD	0x2
+#define SGXMKIF_CC_INVAL_BIF_SL	0x4
+#define SGXMKIF_CC_INVAL_DATA	0x8
+
+
+/*!
+ ******************************************************************************
+ * SGX microkernel interface structure sizes
+ ******************************************************************************/
+typedef struct _SGX_MISCINFO_STRUCT_SIZES_
+{
+#if defined (SGX_FEATURE_2D_HARDWARE)
+	IMG_UINT32	ui32Sizeof_2DCMD;
+	IMG_UINT32	ui32Sizeof_2DCMD_SHARED;
+#endif
+	IMG_UINT32	ui32Sizeof_CMDTA;
+	IMG_UINT32	ui32Sizeof_CMDTA_SHARED;
+	IMG_UINT32	ui32Sizeof_TRANSFERCMD;
+	IMG_UINT32	ui32Sizeof_TRANSFERCMD_SHARED;
+	IMG_UINT32	ui32Sizeof_3DREGISTERS;
+	IMG_UINT32	ui32Sizeof_HWPBDESC;
+	IMG_UINT32	ui32Sizeof_HWRENDERCONTEXT;
+	IMG_UINT32	ui32Sizeof_HWRENDERDETAILS;
+	IMG_UINT32	ui32Sizeof_HWRTDATA;
+	IMG_UINT32	ui32Sizeof_HWRTDATASET;
+	IMG_UINT32	ui32Sizeof_HWTRANSFERCONTEXT;
+	IMG_UINT32	ui32Sizeof_HOST_CTL;
+	IMG_UINT32	ui32Sizeof_COMMAND;
+#if defined(USE_64BIT_COMPAT)
+	IMG_UINT32  ui32Padding;
+#endif
+} SGX_MISCINFO_STRUCT_SIZES;
+
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+/*!
+ *****************************************************************************
+ * SGX misc info for accessing device memory from ukernel
+ *****************************************************************************
+ */
+typedef struct _PVRSRV_SGX_MISCINFO_MEMACCESS
+{
+	IMG_DEV_VIRTADDR	sDevVAddr;		/*!< dev virtual addr for mem access */
+	IMG_DEV_PHYADDR		sPDDevPAddr;	/*!< device physical addr of PD for the mem heap */
+} PVRSRV_SGX_MISCINFO_MEMACCESS;
+#endif
+
+/*!
+ *****************************************************************************
+ * SGX Misc Info structure used in the microkernel
+ * PVRSRV_SGX_MISCINFO_FEATURES is defined in sgxapi_km.h
+ ****************************************************************************/
+typedef struct _PVRSRV_SGX_MISCINFO_INFO
+{
+	IMG_UINT32						ui32MiscInfoFlags;
+	PVRSRV_SGX_MISCINFO_FEATURES	sSGXFeatures;		/*!< external info for client */
+	SGX_MISCINFO_STRUCT_SIZES		sSGXStructSizes;	/*!< internal info: microkernel structure sizes */
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	PVRSRV_SGX_MISCINFO_MEMACCESS	sSGXMemAccessSrc;	/*!< internal info: for reading dev memory */
+	PVRSRV_SGX_MISCINFO_MEMACCESS	sSGXMemAccessDest;	/*!< internal info: for writing dev memory */
+#endif
+} PVRSRV_SGX_MISCINFO_INFO;
+
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+/*!
+ *****************************************************************************
+ * Number of entries in the microkernel status buffer
+ *****************************************************************************/
+#define SGXMK_TRACE_BUFFER_SIZE 512
+#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
+
+#define SGXMKIF_HWPERF_CB_SIZE					0x100	/* must be 2^n*/
+
+/*!
+ *****************************************************************************
+ * One entry in the HWPerf Circular Buffer.
+ *****************************************************************************/
+typedef struct _SGXMKIF_HWPERF_CB_ENTRY_
+{
+	IMG_UINT32	ui32FrameNo;
+	IMG_UINT32	ui32PID;
+	IMG_UINT32	ui32RTData;
+	IMG_UINT32	ui32Type;
+	IMG_UINT32	ui32Ordinal;
+	IMG_UINT32	ui32Info;
+	IMG_UINT32	ui32TimeWraps;
+	IMG_UINT32	ui32Time;
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	IMG_UINT32	ui32SystraceIndex;
+#endif
+	/* NOTE: There should always be at least as many 3D cores as TA cores. */
+	IMG_UINT32	ui32Counters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+	IMG_UINT32	ui32MiscCounters[SGX_FEATURE_MP_CORE_COUNT_3D][PVRSRV_SGX_HWPERF_NUM_MISC_COUNTERS];
+} SGXMKIF_HWPERF_CB_ENTRY;
+
+/*!
+ *****************************************************************************
+ * The HWPerf Circular Buffer.
+ *****************************************************************************/
+typedef struct _SGXMKIF_HWPERF_CB_
+{
+	IMG_UINT32				ui32Woff;
+	IMG_UINT32				ui32Roff;
+	IMG_UINT32				ui32Ordinal;
+	SGXMKIF_HWPERF_CB_ENTRY psHWPerfCBData[SGXMKIF_HWPERF_CB_SIZE];
+} SGXMKIF_HWPERF_CB;
+
+
+#endif /*  __SGX_MKIF_KM_H__ */
+
+/******************************************************************************
+ End of file (sgx_mkif_km.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/pvr/services4/include/sgx_ukernel_status_codes.h b/drivers/gpu/pvr/services4/include/sgx_ukernel_status_codes.h
new file mode 100644
index 0000000..75f186d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/sgx_ukernel_status_codes.h
@@ -0,0 +1,998 @@
+/*************************************************************************/ /*!
+@File           sgx_ukernel_status_codes.h
+@Title          SGX microkernel debug status codes
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    SGX microkernel debug status codes
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __SGX_UKERNEL_STATUS_CODES_H__
+#define __SGX_UKERNEL_STATUS_CODES_H__
+
+/*
+	NOTE: Do not add any conditional macros to this file! There must be
+	no use of #if defined(). This file is included in srvkm to print
+	stringified ukernel status codes, it must build identically to
+	srvinit.
+*/
+
+/*
+	Users of this header might define this macro to do something
+	clever; the primary use right now is to generate a switch/case
+	LUT for debugging in srvkm. If you add a new code, make sure it
+	has a corresponding MKTC_ST.
+*/
+#ifndef MKTC_ST
+#define MKTC_ST(x)
+#endif
+
+/*
+	It would be nice to put these definitions into an enumeration, but USEASM
+	only has access to the C preprocessor so macros are required.
+*/
+
+/*
+	Bits 24-31 of these codes (0xAD) are a magic number used to help
+	distinguish between them and other debug information which can be
+	optionally dumped into the status buffer, e.g. sync object values.
+*/
+
+/*
+	Microkernel trace codes
+*/
+#define MKTC_EHEVENT_3DMEMFREE					0xAD000001
+MKTC_ST(MKTC_EHEVENT_3DMEMFREE)
+#define MKTC_EHEVENT_PIXELENDRENDER				0xAD000002
+MKTC_ST(MKTC_EHEVENT_PIXELENDRENDER)
+#define MKTC_EHEVENT_ISPBREAKPOINT				0xAD000004
+MKTC_ST(MKTC_EHEVENT_ISPBREAKPOINT)
+#define MKTC_EHEVENT_TAFINISHED					0xAD000005
+MKTC_ST(MKTC_EHEVENT_TAFINISHED)
+#define MKTC_EHEVENT_OUTOFMEM					0xAD000007
+MKTC_ST(MKTC_EHEVENT_OUTOFMEM)
+#define MKTC_EHEVENT_TATERMINATE				0xAD000008
+MKTC_ST(MKTC_EHEVENT_TATERMINATE)
+#define MKTC_EHEVENT_TIMER						0xAD000009
+MKTC_ST(MKTC_EHEVENT_TIMER)
+#define MKTC_EHEVENT_SWEVENT					0xAD00000A
+MKTC_ST(MKTC_EHEVENT_SWEVENT)
+#define MKTC_EHEVENT_2DCOMPLETE					0xAD00000B
+MKTC_ST(MKTC_EHEVENT_2DCOMPLETE)
+
+#define MKTC_3DEVENT_3DMEMFREE					0xAD000100
+MKTC_ST(MKTC_3DEVENT_3DMEMFREE)
+#define MKTC_3DEVENT_PIXELENDRENDER				0xAD000101
+MKTC_ST(MKTC_3DEVENT_PIXELENDRENDER)
+#define MKTC_3DEVENT_ISPBREAKPOINT				0xAD000102
+MKTC_ST(MKTC_3DEVENT_ISPBREAKPOINT)
+#define MKTC_3DEVENT_END						0xAD000104
+MKTC_ST(MKTC_3DEVENT_END)
+#define MKTC_3DLB_3DMEMFREE						0xAD000180
+MKTC_ST(MKTC_3DLB_3DMEMFREE)
+#define MKTC_3DLB_PIXELENDRENDER				0xAD000181
+MKTC_ST(MKTC_3DLB_PIXELENDRENDER)
+#define MKTC_3DLB_ISPBREAKPOINT					0xAD000182
+MKTC_ST(MKTC_3DLB_ISPBREAKPOINT)
+#define MKTC_3DLB_FIND3D						0xAD000183
+MKTC_ST(MKTC_3DLB_FIND3D)
+#define MKTC_3DLB_END							0xAD000184
+MKTC_ST(MKTC_3DLB_END)
+
+#define MKTC_TAEVENT_TAFINISHED					0xAD000200
+MKTC_ST(MKTC_TAEVENT_TAFINISHED)
+#define MKTC_TAEVENT_END						0xAD000202
+MKTC_ST(MKTC_TAEVENT_END)
+#define MKTC_TALB_TAFINISHED					0xAD000280
+MKTC_ST(MKTC_TALB_TAFINISHED)
+#define MKTC_TALB_FINDTA						0xAD000281
+MKTC_ST(MKTC_TALB_FINDTA)
+#define MKTC_TALB_END							0xAD000282
+MKTC_ST(MKTC_TALB_END)
+
+#define MKTC_CRRL_WRITEOPSBLOCKED				0xAD000300
+MKTC_ST(MKTC_CRRL_WRITEOPSBLOCKED)
+#define MKTC_CRRL_READOPSBLOCKED				0xAD000301
+MKTC_ST(MKTC_CRRL_READOPSBLOCKED)
+#define MKTC_CRRL_FOUNDRENDER					0xAD000302
+MKTC_ST(MKTC_CRRL_FOUNDRENDER)
+#define MKTC_CRRL_NORENDER						0xAD000303
+MKTC_ST(MKTC_CRRL_NORENDER)
+#define MKTC_CRRL_TARC_DIFFERENT				0xAD000304
+MKTC_ST(MKTC_CRRL_TARC_DIFFERENT)
+#define MKTC_CRRL_BLOCKEDRC						0xAD000309
+MKTC_ST(MKTC_CRRL_BLOCKEDRC)
+#define MKTC_CRRL_BLOCKEDRTDATA					0xAD00030A
+MKTC_ST(MKTC_CRRL_BLOCKEDRTDATA)
+#define MKTC_CRRL_CONTEXT_SUSPENDED				0xAD00030B
+MKTC_ST(MKTC_CRRL_CONTEXT_SUSPENDED)
+#define MKTC_CRRL_TAWAITINGFORMEM				0xAD00030C
+MKTC_ST(MKTC_CRRL_TAWAITINGFORMEM)
+#define MKTC_CRRL_TAOOMBUTPRIOINV				0xAD00030D
+MKTC_ST(MKTC_CRRL_TAOOMBUTPRIOINV)
+#define MKTC_CRRL_READOPS2BLOCKED				0xAD00030E
+MKTC_ST(MKTC_CRRL_READOPS2BLOCKED)
+#define MKTC_CRRL_SRC_WRITEOPSBLOCKED			0xAD00030F
+MKTC_ST(MKTC_CRRL_SRC_WRITEOPSBLOCKED)
+#define MKTC_CRRL_SRC_READOPSBLOCKED			0xAD000310
+MKTC_ST(MKTC_CRRL_SRC_READOPSBLOCKED)
+#define MKTC_CRRL_TQ_WRITEOPSBLOCKED			0xAD000311
+MKTC_ST(MKTC_CRRL_TQ_WRITEOPSBLOCKED)
+#define MKTC_CRRL_TQ_READOPSBLOCKED				0xAD000312
+MKTC_ST(MKTC_CRRL_TQ_READOPSBLOCKED)
+
+#define MKTC_KICKRENDER_START					0xAD000400
+MKTC_ST(MKTC_KICKRENDER_START)
+#define MKTC_KICKRENDER_OVERLAP					0xAD000401
+MKTC_ST(MKTC_KICKRENDER_OVERLAP)
+#define MKTC_KICKRENDER_ISP_START				0xAD000402
+MKTC_ST(MKTC_KICKRENDER_ISP_START)
+#define MKTC_KICKRENDER_RESUME					0xAD000403
+MKTC_ST(MKTC_KICKRENDER_RESUME)
+#define MKTC_KICKRENDER_CONFIG_REGION_HDRS		0xAD000404
+MKTC_ST(MKTC_KICKRENDER_CONFIG_REGION_HDRS)
+#define MKTC_KICKRENDER_END						0xAD000408
+MKTC_ST(MKTC_KICKRENDER_END)
+#define MKTC_KICKRENDER_RENDERCONTEXT			0xAD000409
+MKTC_ST(MKTC_KICKRENDER_RENDERCONTEXT)
+#define MKTC_KICKRENDER_RTDATA					0xAD00040A
+MKTC_ST(MKTC_KICKRENDER_RTDATA)
+#define MKTC_KICKRENDER_PID						0xAD00040B
+MKTC_ST(MKTC_KICKRENDER_PID)
+
+#define MKTC_RENDERFINISHED_START				0xAD000500
+MKTC_ST(MKTC_RENDERFINISHED_START)
+#define MKTC_RF_START_NEXT_MT					0xAD000501
+MKTC_ST(MKTC_RF_START_NEXT_MT)
+#define MKTC_RF_ALL_MTS_DONE					0xAD000502
+MKTC_ST(MKTC_RF_ALL_MTS_DONE)
+#define MKTC_RENDERFINISHED_END					0xAD000503
+MKTC_ST(MKTC_RENDERFINISHED_END)
+#define MKTC_VISQUERY_START						0xAD000504
+MKTC_ST(MKTC_VISQUERY_START)
+#define MKTC_VISQUERY_END						0xAD000505
+MKTC_ST(MKTC_VISQUERY_END)
+#define MKTC_TRANSFERRENDERFINISHED_START		0xAD000508
+MKTC_ST(MKTC_TRANSFERRENDERFINISHED_START)
+#define MKTC_TRANSFERRENDERFINISHED_END			0xAD000509
+MKTC_ST(MKTC_TRANSFERRENDERFINISHED_END)
+#define MKTC_TRF_UPDATESTATUSVALS				0xAD00050A
+MKTC_ST(MKTC_TRF_UPDATESTATUSVALS)
+#define MKTC_TRF_UPDATESTATUSVALS_DONE			0xAD00050B
+MKTC_ST(MKTC_TRF_UPDATESTATUSVALS_DONE)
+
+#define MKTC_PIXELENDRENDER_START				0xAD000600
+MKTC_ST(MKTC_PIXELENDRENDER_START)
+#define MKTC_PIXELENDRENDER_AFTERLOCK			0xAD000601
+MKTC_ST(MKTC_PIXELENDRENDER_AFTERLOCK)
+#define MKTC_PIXELENDRENDER_END					0xAD000602
+MKTC_ST(MKTC_PIXELENDRENDER_END)
+#define MKTC_PIXELENDRENDER_TLQEND				0xAD000603
+MKTC_ST(MKTC_PIXELENDRENDER_TLQEND)
+
+#define MKTC_3DMEMFREE_START					0xAD000700
+MKTC_ST(MKTC_3DMEMFREE_START)
+#define MKTC_3DMEMFREE_AFTERLOCK				0xAD000701
+MKTC_ST(MKTC_3DMEMFREE_AFTERLOCK)
+#define MKTC_3DMEMFREE_TESTEOR					0xAD000702
+MKTC_ST(MKTC_3DMEMFREE_TESTEOR)
+#define MKTC_3DMEMFREE_END						0xAD000703
+MKTC_ST(MKTC_3DMEMFREE_END)
+
+#define MKTC_KICKTA_START						0xAD000800
+MKTC_ST(MKTC_KICKTA_START)
+#define MKTC_KICKTA_OVERLAP						0xAD000801
+MKTC_ST(MKTC_KICKTA_OVERLAP)
+#define MKTC_KICKTA_RESETCONTEXT				0xAD000802
+MKTC_ST(MKTC_KICKTA_RESETCONTEXT)
+#define MKTC_KICKTA_VDM_START					0xAD000803
+MKTC_ST(MKTC_KICKTA_VDM_START)
+#define MKTC_KICKTA_END							0xAD000804
+MKTC_ST(MKTC_KICKTA_END)
+#define MKTC_KICKTA_RENDERCONTEXT				0xAD000805
+MKTC_ST(MKTC_KICKTA_RENDERCONTEXT)
+#define MKTC_KICKTA_RTDATA						0xAD000806
+MKTC_ST(MKTC_KICKTA_RTDATA)
+#define MKTC_KICKTA_RESET_VDMCSSTATUS			0xAD000807
+MKTC_ST(MKTC_KICKTA_RESET_VDMCSSTATUS)
+#define MKTC_KICKTA_RESET_BUFFERS				0xAD000808
+MKTC_ST(MKTC_KICKTA_RESET_BUFFERS)
+#define MKTC_KICKTA_PID							0xAD000809
+MKTC_ST(MKTC_KICKTA_PID)
+#define MKTC_KICKTA_TACMD_DEBUG					0xAD00080A
+MKTC_ST(MKTC_KICKTA_TACMD_DEBUG)
+#define MKTC_KICKTA_FREECONTEXT					0xAD00080B
+MKTC_ST(MKTC_KICKTA_FREECONTEXT)
+#define MKTC_KICKTA_PIM_PATCHING				0xAD00080C
+MKTC_ST(MKTC_KICKTA_PIM_PATCHING)
+#define MKTC_KICKTA_TPC_CHECK_START				0xAD00080D
+MKTC_ST(MKTC_KICKTA_TPC_CHECK_START)
+#define MKTC_KICKTA_TPC_CHECK_END				0xAD00080E
+MKTC_ST(MKTC_KICKTA_TPC_CHECK_END)
+#define MKTC_KICKTA_TPC_CHECK_CORE				0xAD00080F
+MKTC_ST(MKTC_KICKTA_TPC_CHECK_CORE)
+#define MKTC_KICKTA_TPC_CHECK_FAIL				0xAD000810
+MKTC_ST(MKTC_KICKTA_TPC_CHECK_FAIL)
+
+#define MKTC_KICKTA_CHKPT_START_DUMMY_CS		0xAD0008A1
+MKTC_ST(MKTC_KICKTA_CHKPT_START_DUMMY_CS)
+#define MKTC_KICKTA_CHKPT_START_DUMMY_TAK		0xAD0008A2
+MKTC_ST(MKTC_KICKTA_CHKPT_START_DUMMY_TAK)
+#define MKTC_KICKTA_CHKPT_WAIT_FOR_DUMMY_KICK	0xAD0008A3
+MKTC_ST(MKTC_KICKTA_CHKPT_WAIT_FOR_DUMMY_KICK)
+#define MKTC_KICKTA_CHKPT_WAIT_NEXT_CORE		0xAD0008A4
+MKTC_ST(MKTC_KICKTA_CHKPT_WAIT_NEXT_CORE)
+#define MKTC_KICKTA_CHKPT_RESET_COMPLETE		0xAD0008A5
+MKTC_ST(MKTC_KICKTA_CHKPT_RESET_COMPLETE)
+#define MKTC_KICKTA_CHKPT_CHECK_SWITCH			0xAD0008A6
+MKTC_ST(MKTC_KICKTA_CHKPT_CHECK_SWITCH)
+
+#define MKTC_KICK_MEM_BURSTER_WA_VDM_START		0xAD0008B1
+MKTC_ST(MKTC_KICK_MEM_BURSTER_WA_VDM_START)
+#define MKTC_TAFINISHED_MEM_BURSTER_WA			0xAD0008B2
+MKTC_ST(MKTC_TAFINISHED_MEM_BURSTER_WA)
+
+#define MKTC_HOSTKICK_START						0xAD000900
+MKTC_ST(MKTC_HOSTKICK_START)
+#define MKTC_HOSTKICK_END						0xAD000901
+MKTC_ST(MKTC_HOSTKICK_END)
+#define MKTC_HOSTKICK_PROCESS_QUEUES_END		0xAD000902
+MKTC_ST(MKTC_HOSTKICK_PROCESS_QUEUES_END)
+#define MKTC_HOSTKICK_2D						0xAD000903
+MKTC_ST(MKTC_HOSTKICK_2D)
+#define MKTC_HOSTKICK_TRANSFER					0xAD000904
+MKTC_ST(MKTC_HOSTKICK_TRANSFER)
+#define MKTC_HOSTKICK_TA						0xAD000905
+MKTC_ST(MKTC_HOSTKICK_TA)
+#define MKTC_HOSTKICK_PROCESS_QUEUES			0xAD000906
+MKTC_ST(MKTC_HOSTKICK_PROCESS_QUEUES)
+#define MKTC_HOSTKICK_RESUME					0xAD000908
+MKTC_ST(MKTC_HOSTKICK_RESUME)
+#define MKTC_HOSTKICK_POWEROFF					0xAD000909
+MKTC_ST(MKTC_HOSTKICK_POWEROFF)
+#define MKTC_HOSTKICK_IDLE						0xAD00090A
+MKTC_ST(MKTC_HOSTKICK_IDLE)
+#define MKTC_HOSTKICK_CTXSUSPEND				0xAD00090B
+MKTC_ST(MKTC_HOSTKICK_CTXSUSPEND)
+#define MKTC_HOSTKICK_CTXRESUME					0xAD00090C
+MKTC_ST(MKTC_HOSTKICK_CTXRESUME)
+
+#define MKTC_TIMER_POTENTIAL_TA_LOCKUP			0xAD000A00
+MKTC_ST(MKTC_TIMER_POTENTIAL_TA_LOCKUP)
+#define MKTC_TIMER_POTENTIAL_3D_LOCKUP			0xAD000A01
+MKTC_ST(MKTC_TIMER_POTENTIAL_3D_LOCKUP)
+#define MKTC_TIMER_CTAL_START					0xAD000A02
+MKTC_ST(MKTC_TIMER_CTAL_START)
+#define MKTC_TIMER_CTAL_END						0xAD000A03
+MKTC_ST(MKTC_TIMER_CTAL_END)
+#define MKTC_TIMER_C3DL_START					0xAD000A04
+MKTC_ST(MKTC_TIMER_C3DL_START)
+#define MKTC_TIMER_C3DL_END						0xAD000A05
+MKTC_ST(MKTC_TIMER_C3DL_END)
+#define MKTC_TIMER_LOCKUP						0xAD000A0A
+MKTC_ST(MKTC_TIMER_LOCKUP)
+#define MKTC_TIMER_NOT_TA_LOCKUP				0xAD000A0B
+MKTC_ST(MKTC_TIMER_NOT_TA_LOCKUP)
+#define MKTC_TIMER_NOT_3D_LOCKUP				0xAD000A0C
+MKTC_ST(MKTC_TIMER_NOT_3D_LOCKUP)
+#define MKTC_TIMER_2D_LOCKUP					0xAD000A0D
+MKTC_ST(MKTC_TIMER_2D_LOCKUP)
+#define MKTC_TIMER_POTENTIAL_2D_LOCKUP			0xAD000A10
+MKTC_ST(MKTC_TIMER_POTENTIAL_2D_LOCKUP)
+#define MKTC_TIMER_C2DL_START					0xAD000A11
+MKTC_ST(MKTC_TIMER_C2DL_START)
+#define MKTC_TIMER_C2DL_END						0xAD000A12
+MKTC_ST(MKTC_TIMER_C2DL_END)
+#define MKTC_TIMER_NOT_2D_LOCKUP				0xAD000A13
+MKTC_ST(MKTC_TIMER_NOT_2D_LOCKUP)
+#define MKTC_TIMER_ABORTALL						0xAD000A0E
+MKTC_ST(MKTC_TIMER_ABORTALL)
+#define MKTC_TIMER_END							0xAD000A0F
+MKTC_ST(MKTC_TIMER_END)
+
+#define MKTC_HWR_START							0xAD000B00
+MKTC_ST(MKTC_HWR_START)
+#define MKTC_HWR_END							0xAD000B01
+MKTC_ST(MKTC_HWR_END)
+#define MKTC_HWR_HKS							0xAD000B02
+MKTC_ST(MKTC_HWR_HKS)
+#define MKTC_HWR_PRL							0xAD000B03
+MKTC_ST(MKTC_HWR_PRL)
+#define MKTC_HWR_PRL_DP							0xAD000B04
+MKTC_ST(MKTC_HWR_PRL_DP)
+#define MKTC_HWR_CRL							0xAD000B05
+MKTC_ST(MKTC_HWR_CRL)
+#define MKTC_HWR_CRL_DP							0xAD000B06
+MKTC_ST(MKTC_HWR_CRL_DP)
+#define MKTC_HWR_TRL							0xAD000B07
+MKTC_ST(MKTC_HWR_TRL)
+#define MKTC_HWR_TRL_DP							0xAD000B08
+MKTC_ST(MKTC_HWR_TRL_DP)
+#define MKTC_HWR_ISC							0xAD000B09
+MKTC_ST(MKTC_HWR_ISC)
+#define MKTC_HWR_2DL							0xAD000B0A
+MKTC_ST(MKTC_HWR_2DL)
+#define MKTC_HWR_CLEANUP						0xAD000B0B
+MKTC_ST(MKTC_HWR_CLEANUP)
+
+#define MKTC_URSV_START							0xAD000C00
+MKTC_ST(MKTC_URSV_START)
+#define MKTC_URSV_UPDATEWRITEOPS				0xAD000C01
+MKTC_ST(MKTC_URSV_UPDATEWRITEOPS)
+#define MKTC_URSV_UPDATESTATUSVALS				0xAD000C03
+MKTC_ST(MKTC_URSV_UPDATESTATUSVALS)
+#define MKTC_URSV_UPDATESTATUSVALS_DONE			0xAD000C04
+MKTC_ST(MKTC_URSV_UPDATESTATUSVALS_DONE)
+#define MKTC_URSV_END							0xAD000C05
+MKTC_ST(MKTC_URSV_END)
+
+#define MKTC_STORETACONTEXT_START				0xAD000D00
+MKTC_ST(MKTC_STORETACONTEXT_START)
+#define MKTC_STORETACONTEXT_END					0xAD000D01
+MKTC_ST(MKTC_STORETACONTEXT_END)
+#define MKTC_LOADTACONTEXT_START				0xAD000D02
+MKTC_ST(MKTC_LOADTACONTEXT_START)
+#define MKTC_LOADTACONTEXT_END					0xAD000D03
+MKTC_ST(MKTC_LOADTACONTEXT_END)
+#define MKTC_STORE3DCONTEXT_START				0xAD000D04
+MKTC_ST(MKTC_STORE3DCONTEXT_START)
+#define MKTC_STORE3DCONTEXT_END					0xAD000D05
+MKTC_ST(MKTC_STORE3DCONTEXT_END)
+#define MKTC_LOAD3DCONTEXT_START				0xAD000D06
+MKTC_ST(MKTC_LOAD3DCONTEXT_START)
+#define MKTC_LOAD3DCONTEXT_END					0xAD000D07
+MKTC_ST(MKTC_LOAD3DCONTEXT_END)
+
+#define MKTC_FINDTA_POWERREQUEST				0xAD000E00
+MKTC_ST(MKTC_FINDTA_POWERREQUEST)
+#define MKTC_FINDTA_TA3D_OVERLAP_BLOCKED		0xAD000E01
+MKTC_ST(MKTC_FINDTA_TA3D_OVERLAP_BLOCKED)
+#define MKTC_FINDTA_RTDATA_RENDERING			0xAD000E02
+MKTC_ST(MKTC_FINDTA_RTDATA_RENDERING)
+#define MKTC_FINDTA_3DRC_DIFFERENT				0xAD000E03
+MKTC_ST(MKTC_FINDTA_3DRC_DIFFERENT)
+#define MKTC_FINDTA_WRITEOPSBLOCKED				0xAD000E04
+MKTC_ST(MKTC_FINDTA_WRITEOPSBLOCKED)
+#define MKTC_FINDTA_READOPSBLOCKED				0xAD000E05
+MKTC_ST(MKTC_FINDTA_READOPSBLOCKED)
+#define MKTC_FINDTA_RESIZE_PB					0xAD000E06
+MKTC_ST(MKTC_FINDTA_RESIZE_PB)
+#define MKTC_FINDTA_RESIZE_PB_BLOCKED			0xAD000E07
+MKTC_ST(MKTC_FINDTA_RESIZE_PB_BLOCKED)
+#define MKTC_FINDTA_SHRINK_PB					0xAD000E08
+MKTC_ST(MKTC_FINDTA_SHRINK_PB)
+#define	MKTC_FINDTA_TAPB_DIFFERENT				0xAD000E09
+MKTC_ST(MKTC_FINDTA_TAPB_DIFFERENT)
+#define	MKTC_FINDTA_TACONTEXT_DIFFERENT			0xAD000E0A
+MKTC_ST(MKTC_FINDTA_TACONTEXT_DIFFERENT)
+#define MKTC_FINDTA_TA2D_OVERLAP_BLOCKED		0xAD000E0B
+MKTC_ST(MKTC_FINDTA_TA2D_OVERLAP_BLOCKED)
+#define MKTC_FINDTA_CONTEXT_SUSPENDED			0xAD000E0C
+MKTC_ST(MKTC_FINDTA_CONTEXT_SUSPENDED)
+#define MKTC_FINDTA_SRC_READOPSBLOCKED			0xAD000E0D
+MKTC_ST(MKTC_FINDTA_SRC_READOPSBLOCKED)
+#define MKTC_FINDTA_SRC_WRITEOPSBLOCKED			0xAD000E0E
+MKTC_ST(MKTC_FINDTA_SRC_WRITEOPSBLOCKED)
+#define MKTC_FINDTA_READOPS2BLOCKED				0xAD000E0F
+MKTC_ST(MKTC_FINDTA_READOPS2BLOCKED)
+
+
+#define MKTC_CTRL_SRCREADOPSBLOCKED				0xAD000F00
+MKTC_ST(MKTC_CTRL_SRCREADOPSBLOCKED)
+#define MKTC_CTRL_SRCWRITEOPSBLOCKED			0xAD000F01
+MKTC_ST(MKTC_CTRL_SRCWRITEOPSBLOCKED)
+#define MKTC_CTRL_DSTREADOPSBLOCKED				0xAD000F02
+MKTC_ST(MKTC_CTRL_DSTREADOPSBLOCKED)
+#define MKTC_CTRL_DSTWRITEOPSBLOCKED			0xAD000F03
+MKTC_ST(MKTC_CTRL_DSTWRITEOPSBLOCKED)
+#define MKTC_CTRL_TARC_DIFFERENT				0xAD000F04
+MKTC_ST(MKTC_CTRL_TARC_DIFFERENT)
+#define MKTC_CTRL_CONTEXT_SUSPENDED				0xAD000F05
+MKTC_ST(MKTC_CTRL_CONTEXT_SUSPENDED)
+#define MKTC_CTRL_SRCREADOPS2BLOCKED			0xAD000F06
+MKTC_ST(MKTC_CTRL_SRCREADOPS2BLOCKED)
+#define MKTC_CTRL_3D_WRITEOPSBLOCKED			0xAD000F07
+MKTC_ST(MKTC_CTRL_3D_WRITEOPSBLOCKED)
+#define MKTC_CTRL_3D_READOPSBLOCKED				0xAD000F08
+MKTC_ST(MKTC_CTRL_3D_READOPSBLOCKED)
+
+#define MKTC_DPTA_START							0xAD001000
+MKTC_ST(MKTC_DPTA_START)
+#define MKTC_DPTA_UPDATESTATUSVALS				0xAD001001
+MKTC_ST(MKTC_DPTA_UPDATESTATUSVALS)
+#define MKTC_DPTA_UPDATESTATUSVALS_DONE			0xAD001002
+MKTC_ST(MKTC_DPTA_UPDATESTATUSVALS_DONE)
+#define MKTC_DPTA_NORENDER						0xAD001003
+MKTC_ST(MKTC_DPTA_NORENDER)
+#define MKTC_DPTA_MEMFREE						0xAD001004
+MKTC_ST(MKTC_DPTA_MEMFREE)
+#define MKTC_DPTA_INC_COMPLETECOUNT				0xAD001005
+MKTC_ST(MKTC_DPTA_INC_COMPLETECOUNT)
+
+#define MKTC_INVALDC 							0xAD001100
+MKTC_ST(MKTC_INVALDC)
+#define MKTC_INVALPT 							0xAD001101
+MKTC_ST(MKTC_INVALPT)
+#define MKTC_INVALSLC							0xAD001102
+MKTC_ST(MKTC_INVALSLC)
+#define MKTC_INVALDATA							0xAD001103
+MKTC_ST(MKTC_INVALDATA)
+
+#define MKTC_RESTARTTA							0xAD001200
+MKTC_ST(MKTC_RESTARTTA)
+#define MKTC_CSABORTNONGBL						0xAD001201
+MKTC_ST(MKTC_CSABORTNONGBL)
+#define MKTC_CSABORTALL							0xAD001202
+MKTC_ST(MKTC_CSABORTALL)
+#define MKTC_CSRENDERINPROGRESS					0xAD001203
+MKTC_ST(MKTC_CSRENDERINPROGRESS)
+#define MKTC_TATERMRENDERINPROGRESS				0xAD001204
+MKTC_ST(MKTC_TATERMRENDERINPROGRESS)
+#define MKTC_RESTARTTANORENDER					0xAD001205
+MKTC_ST(MKTC_RESTARTTANORENDER)
+#define MKTC_SPM_KICKRENDER						0xAD001206
+MKTC_ST(MKTC_SPM_KICKRENDER)
+#define MKTC_SPM_RESUME_ABORTCOMPLETE			0xAD001208
+MKTC_ST(MKTC_SPM_RESUME_ABORTCOMPLETE)
+#define	MKTC_RESUMEVDM							0xAD001209
+MKTC_ST(MKTC_RESUMEVDM)
+#define	MKTC_REMOVE_RESERVE_MEM					0xAD00120A
+MKTC_ST(MKTC_REMOVE_RESERVE_MEM)
+#define	MKTC_INCREASEZLSTHRESHOLD				0xAD00120B
+MKTC_ST(MKTC_INCREASEZLSTHRESHOLD)
+#define MKTC_CSFORCEABORTALL					0xAD00120C
+MKTC_ST(MKTC_CSFORCEABORTALL)
+
+#define MKTC_DUMMY_DEPTH						0xAD00120D
+MKTC_ST(MKTC_DUMMY_DEPTH)
+#define MKTC_DUMMY_DEPTH_CS						0xAD00120E
+MKTC_ST(MKTC_DUMMY_DEPTH_CS)
+
+#define MKTC_MTETE_OOM							0xAD00120F
+MKTC_ST(MKTC_MTETE_OOM)
+#define	MKTC_MTETE_OOM_FIRST_STORE_REF			0xAD001210
+MKTC_ST(MKTC_MTETE_OOM_FIRST_STORE_REF)
+#define MKTC_MERGE_STATE_TABLES					0xAD001211
+MKTC_ST(MKTC_MERGE_STATE_TABLES)
+#define MKTC_NO_PAGES_LEFT_FOR_23055			0xAD001212
+MKTC_ST(MKTC_NO_PAGES_LEFT_FOR_23055)
+#define MKTC_NO_STATE_MODS						0xAD001213
+MKTC_ST(MKTC_NO_STATE_MODS)
+#define MKTC_FIND_MTE_PAGE_IN_STATE				0xAD001214
+MKTC_ST(MKTC_FIND_MTE_PAGE_IN_STATE)
+#define MKTC_MTE_PAGE_FOUND						0xAD001215
+MKTC_ST(MKTC_MTE_PAGE_FOUND)
+#define MKTC_MOVE_MTE_PAGE_TO_TA_STATE			0xAD001216
+MKTC_ST(MKTC_MOVE_MTE_PAGE_TO_TA_STATE)
+#define MKTC_MOVE_MTE_PAGE_TO_TA_STATE_END		0xAD001217
+MKTC_ST(MKTC_MOVE_MTE_PAGE_TO_TA_STATE_END)
+#define MKTC_ZERO_ZLS_THRESHOLD					0xAD001218
+MKTC_ST(MKTC_ZERO_ZLS_THRESHOLD)
+#define MKTC_RESTORE_ZLS_THRESHOLD				0xAD001219
+MKTC_ST(MKTC_RESTORE_ZLS_THRESHOLD)
+#define MKTC_FIND_MTE_PAGE_IN_CSM				0xAD00121A
+MKTC_ST(MKTC_FIND_MTE_PAGE_IN_CSM)
+#define MKTC_REISSUE_MTE_PAGE					0xAD00121B
+MKTC_ST(MKTC_REISSUE_MTE_PAGE)
+#define MKTC_REISSUE_MTE_PAGE_REQUIRED			0xAD00121C
+MKTC_ST(MKTC_REISSUE_MTE_PAGE_REQUIRED)
+#define MKTC_REISSUE_MTE_PAGE_END				0xAD00121D
+MKTC_ST(MKTC_REISSUE_MTE_PAGE_END)
+#define MKTC_RESET_TE_PSG						0xAD00121E
+MKTC_ST(MKTC_RESET_TE_PSG)
+
+#define MKTC_OOM_WRITEOPSBLOCKED				0xAD00121F
+MKTC_ST(MKTC_OOM_WRITEOPSBLOCKED)
+#define MKTC_OOM_READOPSBLOCKED					0xAD001220
+MKTC_ST(MKTC_OOM_READOPSBLOCKED)
+#define MKTC_OOM_SRC_WRITEOPSBLOCKED			0xAD001221
+MKTC_ST(MKTC_OOM_SRC_WRITEOPSBLOCKED)
+#define MKTC_OOM_SRC_READOPSBLOCKED				0xAD001222
+MKTC_ST(MKTC_OOM_SRC_READOPSBLOCKED)
+#define MKTC_OOM_SPM_DEADLOCK					0xAD001223
+MKTC_ST(MKTC_OOM_SPM_DEADLOCK)
+#define MKTC_OOM_SPM_DEADLOCK_MEM_ADDED			0xAD001224
+MKTC_ST(MKTC_OOM_SPM_DEADLOCK_MEM_ADDED)
+#define MKTC_RESET								0xAD001225
+MKTC_ST(MKTC_RESET)
+#define	MKTC_SPM_INVALID_ZLSCONFIG				0xAD001226
+MKTC_ST(MKTC_SPM_INVALID_ZLSCONFIG)
+#define MKTC_SPM_DEADLOCK_RENDER_FINISHED			0xAD001227
+MKTC_ST(MKTC_SPM_DEADLOCK_RENDER_FINISHED)
+#define MKTC_OOM_BLOCKEDRTDATA					0xAD001228
+MKTC_ST(MKTC_OOM_BLOCKEDRTDATA)
+
+#define MKTC_OOM_TYPE_MT						0xAD00122A
+MKTC_ST(MKTC_OOM_TYPE_MT)
+#define MKTC_OOM_TYPE_GLOBAL					0xAD001230
+MKTC_ST(MKTC_OOM_TYPE_GLOBAL)
+#define MKTC_OOM_CAUSE_GBL_OOM					0xAD001231
+MKTC_ST(MKTC_OOM_CAUSE_GBL_OOM)
+#define MKTC_OOM_RESTORE_LIST_SIZE				0xAD001232
+MKTC_ST(MKTC_OOM_RESTORE_LIST_SIZE)
+
+#define MKTC_CHECK_MTE_PAGE_REISSUE				0xAD001240
+MKTC_ST(MKTC_CHECK_MTE_PAGE_REISSUE)
+#define MKTC_CPRI_VALID_ENTRIES					0xAD001241
+MKTC_ST(MKTC_CPRI_VALID_ENTRIES)
+#define MKTC_CPRI_STORE_DPLIST					0xAD001242
+MKTC_ST(MKTC_CPRI_STORE_DPLIST)
+#define MKTC_CPRI_STORE_OTPM_CSM				0xAD001243
+MKTC_ST(MKTC_CPRI_STORE_OTPM_CSM)
+#define MKTC_CPRI_ABORT_MT_IDX					0xAD001244
+MKTC_ST(MKTC_CPRI_ABORT_MT_IDX)
+#define MKTC_CPRI_ABORT_CORE_IDX				0xAD001245
+MKTC_ST(MKTC_CPRI_ABORT_CORE_IDX)
+#define MKTC_CPRI_CSM_TABLE_DATA				0xAD001246
+MKTC_ST(MKTC_CPRI_CSM_TABLE_DATA)
+#define MKTC_CPRI_PIM_DATA						0xAD001247
+MKTC_ST(MKTC_CPRI_PIM_DATA)
+#define MKTC_CPRI_DO_CIRCULAR_TEST				0xAD001248
+MKTC_ST(MKTC_CPRI_DO_CIRCULAR_TEST)
+#define MKTC_CPRI_WRITE_ENTRIES					0xAD001249
+MKTC_ST(MKTC_CPRI_WRITE_ENTRIES)
+
+#define	MKTC_MTE_ENTRY_NOT_IN_ANY_LIST			0xAD001250
+MKTC_ST(MKTC_MTE_ENTRY_NOT_IN_ANY_LIST)
+
+#define	MKTC_SPMAC_IGNORE_TERMINATE				0xAD001251
+MKTC_ST(MKTC_SPMAC_IGNORE_TERMINATE)
+
+#define MKTC_SPMAC_REQUEST_3D_TIMEOUT			0xAD001252
+MKTC_ST(MKTC_SPMAC_REQUEST_3D_TIMEOUT)
+#define MKTC_SPMAC_3D_TIMEOUT_COMPLETE			0xAD001253
+MKTC_ST(MKTC_SPMAC_3D_TIMEOUT_COMPLETE)
+#define MKTC_OOM_READOPS2BLOCKED				0xAD001254
+MKTC_ST(MKTC_OOM_READOPS2BLOCKED)
+
+/* PB Load/store status */
+#define MKTC_LOADTAPB_START						0xAD001300
+MKTC_ST(MKTC_LOADTAPB_START)
+#define MKTC_LOADTAPB_END						0xAD001301
+MKTC_ST(MKTC_LOADTAPB_END)
+#define MKTC_STORETAPB_START					0xAD001302
+MKTC_ST(MKTC_STORETAPB_START)
+#define MKTC_STORETAPB_END						0xAD001303
+MKTC_ST(MKTC_STORETAPB_END)
+#define MKTC_LOAD3DPB_START						0xAD001304
+MKTC_ST(MKTC_LOAD3DPB_START)
+#define MKTC_LOAD3DPB_END						0xAD001305
+MKTC_ST(MKTC_LOAD3DPB_END)
+#define MKTC_STORE3DPB_START					0xAD001306
+MKTC_ST(MKTC_STORE3DPB_START)
+#define MKTC_STORE3DPB_END						0xAD001307
+MKTC_ST(MKTC_STORE3DPB_END)
+#define MKTC_LOADTAPB_PAGETABLE_DONE			0xAD001308
+MKTC_ST(MKTC_LOADTAPB_PAGETABLE_DONE)
+#define MKTC_LOAD3DPB_PAGETABLE_DONE			0xAD001309
+MKTC_ST(MKTC_LOAD3DPB_PAGETABLE_DONE)
+
+#define MKTC_TIMER_RC_CLEANUP					0xAD001400
+MKTC_ST(MKTC_TIMER_RC_CLEANUP)
+#define MKTC_TIMER_RC_CLEANUP_DONE				0xAD001401
+MKTC_ST(MKTC_TIMER_RC_CLEANUP_DONE)
+#define MKTC_TIMER_RC_CLEANUP_BUSY				0xAD001402
+MKTC_ST(MKTC_TIMER_RC_CLEANUP_BUSY)
+#define MKTC_TIMER_RT_CLEANUP					0xAD001410
+MKTC_ST(MKTC_TIMER_RT_CLEANUP)
+#define MKTC_TIMER_RT_CLEANUP_DONE				0xAD001411
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_DONE)
+#define MKTC_TIMER_RT_CLEANUP_PENDING			0xAD001412
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_PENDING)
+#define MKTC_TIMER_RT_CLEANUP_TIDYPARTIALLIST	0xAD001413
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_TIDYPARTIALLIST)
+#define MKTC_TIMER_RT_CLEANUP_BUSY				0xAD001414
+MKTC_ST(MKTC_TIMER_RT_CLEANUP_BUSY)
+#define MKTC_TIMER_TC_CLEANUP					0xAD001420
+MKTC_ST(MKTC_TIMER_TC_CLEANUP)
+#define MKTC_TIMER_TC_CLEANUP_DONE				0xAD001421
+MKTC_ST(MKTC_TIMER_TC_CLEANUP_DONE)
+#define MKTC_TIMER_TC_CLEANUP_BUSY				0xAD001422
+MKTC_ST(MKTC_TIMER_TC_CLEANUP_BUSY)
+#define MKTC_TIMER_2DC_CLEANUP					0xAD001430
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP)
+#define MKTC_TIMER_2DC_CLEANUP_DONE				0xAD001431
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP_DONE)
+#define MKTC_TIMER_2DC_CLEANUP_BUSY				0xAD001432
+MKTC_ST(MKTC_TIMER_2DC_CLEANUP_BUSY)
+#define MKTC_TIMER_SHAREDPBDESC_CLEANUP			0xAD001440
+MKTC_ST(MKTC_TIMER_SHAREDPBDESC_CLEANUP)
+
+
+#define MKTC_TIMER_ISP_SWITCH_POTENTIAL_LOCKUP	0xAD001450
+MKTC_ST(MKTC_TIMER_ISP_SWITCH_POTENTIAL_LOCKUP)
+#define MKTC_TIMER_ISP_SWITCH_FORCE_SWITCH		0xAD001451
+MKTC_ST(MKTC_TIMER_ISP_SWITCH_FORCE_SWITCH)
+
+#define MKTC_UTSO_UPDATEREADOPS					0xAD001600
+MKTC_ST(MKTC_UTSO_UPDATEREADOPS)
+#define MKTC_UTSO_UPDATEWRITEOPS				0xAD001601
+MKTC_ST(MKTC_UTSO_UPDATEWRITEOPS)
+
+#define MKTC_TAFINISHED_UPDATESTATUSVALS		0xAD001700
+MKTC_ST(MKTC_TAFINISHED_UPDATESTATUSVALS)
+#define MKTC_TAFINISHED_UPDATESTATUSVALS_DONE	0xAD001701
+MKTC_ST(MKTC_TAFINISHED_UPDATESTATUSVALS_DONE)
+#define MKTC_TAFINISHED_NORENDER				0xAD001702
+MKTC_ST(MKTC_TAFINISHED_NORENDER)
+#define MKTC_TAFINISHED_LASTKICK				0xAD001703
+MKTC_ST(MKTC_TAFINISHED_LASTKICK)
+#define MKTC_TAFINISHED_FINDRENDER				0xAD001704
+MKTC_ST(MKTC_TAFINISHED_FINDRENDER)
+#define MKTC_TAFINISHED_FINDTA					0xAD001705
+MKTC_ST(MKTC_TAFINISHED_FINDTA)
+#define MKTC_TAFINISHED_END						0xAD001706
+MKTC_ST(MKTC_TAFINISHED_END)
+#define MKTC_TAF_SPM_DEADLOCK_MEM_REMOVED		0xAD001707
+MKTC_ST(MKTC_TAF_SPM_DEADLOCK_MEM_REMOVED)
+#define MKTC_TAF_RESERVE_MEM					0xAD001708
+MKTC_ST(MKTC_TAF_RESERVE_MEM)
+#define MKTC_TAF_RESERVE_MEM_REQUEST_RENDER		0xAD001709
+MKTC_ST(MKTC_TAF_RESERVE_MEM_REQUEST_RENDER)
+#define MKTC_TAF_RESERVE_FREE_RENDER_FINISHED	0xAD00170A
+MKTC_ST(MKTC_TAF_RESERVE_FREE_RENDER_FINISHED)
+#define MKTC_TAF_RESERVE_FREE_DUMMY_RENDER		0xAD00170B
+MKTC_ST(MKTC_TAF_RESERVE_FREE_DUMMY_RENDER)
+#define MKTC_TAF_DEBUG_SAS						0xAD00170C
+MKTC_ST(MKTC_TAF_DEBUG_SAS)
+#define MKTC_TAFINISHED_NOCONTEXTSWITCH			0xAD00170D
+MKTC_ST(MKTC_TAFINISHED_NOCONTEXTSWITCH)
+
+#define MKTC_TAFINISHED_TERM_COMPLETE_START		0xAD001710
+MKTC_ST(MKTC_TAFINISHED_TERM_COMPLETE_START)
+#define MKTC_TAFINISHED_TERM_COMPLETE_END		0xAD001711
+MKTC_ST(MKTC_TAFINISHED_TERM_COMPLETE_END)
+
+#define MKTC_TAFINISHED_DPMPAGERECYCLING			0xAD001720
+MKTC_ST(MKTC_TAFINISHED_DPMPAGERECYCLING)
+
+#define MKTC_2DEVENT_2DCOMPLETE					0xAD001800
+MKTC_ST(MKTC_2DEVENT_2DCOMPLETE)
+#define MKTC_2DEVENT_END						0xAD001801
+MKTC_ST(MKTC_2DEVENT_END)
+#define	MKTC_2DLB_2DCOMPLETE					0xAD001802
+MKTC_ST(MKTC_2DLB_2DCOMPLETE)
+#define MKTC_2DLB_FIND2D						0xAD001803
+MKTC_ST(MKTC_2DLB_FIND2D)
+#define MKTC_2DLB_END							0xAD001804
+MKTC_ST(MKTC_2DLB_END)
+#define MKTC_2DCOMPLETE_START					0xAD001805
+MKTC_ST(MKTC_2DCOMPLETE_START)
+#define MKTC_2DCOMPLETE_END						0xAD001806
+MKTC_ST(MKTC_2DCOMPLETE_END)
+#define MKTC_KICK2D_START						0xAD001807
+MKTC_ST(MKTC_KICK2D_START)
+#define MKTC_KICK2D_END							0xAD001808
+MKTC_ST(MKTC_KICK2D_END)
+#define MKTC_DUMMYPROC2D						0xAD001809
+MKTC_ST(MKTC_DUMMYPROC2D)
+#define MKTC_FTD_SRCREADOPSBLOCKED				0xAD00180A
+MKTC_ST(MKTC_FTD_SRCREADOPSBLOCKED)
+#define MKTC_FTD_SRCWRITEOPSBLOCKED				0xAD00180B
+MKTC_ST(MKTC_FTD_SRCWRITEOPSBLOCKED)
+#define MKTC_FTD_DSTREADOPSBLOCKED				0xAD00180C
+MKTC_ST(MKTC_FTD_DSTREADOPSBLOCKED)
+#define MKTC_FTD_DSTWRITEOPSBLOCKED				0xAD00180D
+MKTC_ST(MKTC_FTD_DSTWRITEOPSBLOCKED)
+#define MKTC_FTD_TA2D_OVERLAP_BLOCKED			0xAD00180E
+MKTC_ST(MKTC_FTD_TA2D_OVERLAP_BLOCKED)
+#define MKTC_U2DSO_UPDATEREADOPS				0xAD00180F
+MKTC_ST(MKTC_U2DSO_UPDATEREADOPS)
+#define MKTC_U2DSO_UPDATEWRITEOPS				0xAD001810
+MKTC_ST(MKTC_U2DSO_UPDATEWRITEOPS)
+#define MKTC_FTD_TAOPSBLOCKED					0xAD001811
+MKTC_ST(MKTC_FTD_TAOPSBLOCKED)
+#define MKTC_KICK2D_2DSLAVEPORT					0xAD001812
+MKTC_ST(MKTC_KICK2D_2DSLAVEPORT)
+#define MKTC_KICK2D_2DSLAVEPORT_DONE			0xAD001813
+MKTC_ST(MKTC_KICK2D_2DSLAVEPORT_DONE)
+#define MKTC_FTD_CONTEXT_SUSPENDED				0xAD001814
+MKTC_ST(MKTC_FTD_CONTEXT_SUSPENDED)
+#define MKTC_KICK2D_PID							0xAD001815
+MKTC_ST(MKTC_KICK2D_PID)
+#define MKTC_FIND2D_ADDR_SPACE_DIFFERENT		0xAD001816
+MKTC_ST(MKTC_FIND2D_ADDR_SPACE_DIFFERENT)
+#define MKTC_FTD_3DOPSBLOCKED					0xAD001817
+MKTC_ST(MKTC_FTD_3DOPSBLOCKED)
+#define MKTC_FTD_DSTREADOPS2BLOCKED				0xAD001818
+MKTC_ST(MKTC_FTD_DSTREADOPS2BLOCKED)
+#define MKTC_U2DSO_UPDATESTATUSVALS				0xAD001819
+MKTC_ST(MKTC_U2DSO_UPDATESTATUSVALS)
+#define MKTC_U2DSO_UPDATESTATUSVALS_DONE		0xAD00181A
+MKTC_ST(MKTC_U2DSO_UPDATESTATUSVALS_DONE)
+
+#define MKTC_FCM_START							0xAD001900
+MKTC_ST(MKTC_FCM_START)
+#define MKTC_FCM_END							0xAD001901
+MKTC_ST(MKTC_FCM_END)
+#define MKTC_FCM_PB_SAME						0xAD001902
+MKTC_ST(MKTC_FCM_PB_SAME)
+#define MKTC_FCM_TQ_IN_PROGESS					0xAD001903
+MKTC_ST(MKTC_FCM_TQ_IN_PROGESS)
+#define MKTC_FCM_TQ_MEMCONTEXT_DIFFERENT		0xAD001904
+MKTC_ST(MKTC_FCM_TQ_MEMCONTEXT_DIFFERENT)
+
+#define MKTC_TIMER_ACTIVE_POWER					0xAD001A00
+MKTC_ST(MKTC_TIMER_ACTIVE_POWER)
+#define MKTC_TIMER_POWER_3D_ACTIVE				0xAD001A01
+MKTC_ST(MKTC_TIMER_POWER_3D_ACTIVE)
+#define MKTC_TIMER_POWER_TA_ACTIVE				0xAD001A02
+MKTC_ST(MKTC_TIMER_POWER_TA_ACTIVE)
+#define MKTC_TIMER_POWER_2D_ACTIVE				0xAD001A03
+MKTC_ST(MKTC_TIMER_POWER_2D_ACTIVE)
+#define MKTC_TIMER_POWER_PENDING_EVENTS			0xAD001A04
+MKTC_ST(MKTC_TIMER_POWER_PENDING_EVENTS)
+#define MKTC_TIMER_POWER_IDLE					0xAD001A05
+MKTC_ST(MKTC_TIMER_POWER_IDLE)
+#define MKTC_TIMER_POWER_OFF					0xAD001A06
+MKTC_ST(MKTC_TIMER_POWER_OFF)
+#define	MKTC_TIMER_POWER_CCB_ERROR				0xAD001A07
+MKTC_ST(MKTC_TIMER_POWER_CCB_ERROR)
+#define	MKTC_TIMER_POWER_RESTART_IMMEDIATE		0xAD001A08
+MKTC_ST(MKTC_TIMER_POWER_RESTART_IMMEDIATE)
+
+#define MKTC_3DCONTEXT_SWITCH					0xAD001B00
+MKTC_ST(MKTC_3DCONTEXT_SWITCH)
+#define MKTC_3DCONTEXT_SWITCH_END				0xAD001B01
+MKTC_ST(MKTC_3DCONTEXT_SWITCH_END)
+
+#define MKTC_TACONTEXT_SWITCH					0xAD001C00
+MKTC_ST(MKTC_TACONTEXT_SWITCH)
+#define MKTC_TACONTEXT_SWITCH_END				0xAD001C02
+MKTC_ST(MKTC_TACONTEXT_SWITCH_END)
+
+#define MKTC_GETMISCINFO_MEMREAD_START			0xAD001D00
+MKTC_ST(MKTC_GETMISCINFO_MEMREAD_START)
+#define MKTC_GETMISCINFO_MEMREAD_END			0xAD001D01
+MKTC_ST(MKTC_GETMISCINFO_MEMREAD_END)
+#define MKTC_GETMISCINFO_MEMWRITE_START			0xAD001D02
+MKTC_ST(MKTC_GETMISCINFO_MEMWRITE_START)
+#define MKTC_GETMISCINFO_MEMWRITE_END			0xAD001D03
+MKTC_ST(MKTC_GETMISCINFO_MEMWRITE_END)
+
+#define	MKTC_HALTTA								0xAD001E00
+MKTC_ST(MKTC_HALTTA)
+#define MKTC_HTA_SET_FLAG						0xAD001E01
+MKTC_ST(MKTC_HTA_SET_FLAG)
+#define MKTC_HTA_SAVE_COMPLEX_PTR				0xAD001E02
+MKTC_ST(MKTC_HTA_SAVE_COMPLEX_PTR)
+#define MKTC_HALTTA_END							0xAD001E03
+MKTC_ST(MKTC_HALTTA_END)
+
+#define	MKTC_RESUMETA							0xAD001F00
+MKTC_ST(MKTC_RESUMETA)
+#define	MKTC_RTA_CONTEXT_LOADED					0xAD001F01
+MKTC_ST(MKTC_RTA_CONTEXT_LOADED)
+#define	MKTC_RTA_MTE_STATE_KICKED				0xAD001F02
+MKTC_ST(MKTC_RTA_MTE_STATE_KICKED)
+#define MKTC_RTA_CMPLX_GEOM_PRESENT				0xAD001F03
+MKTC_ST(MKTC_RTA_CMPLX_GEOM_PRESENT)
+#define	MKTC_RTA_CMPLX_STATE_KICKED				0xAD001F04
+MKTC_ST(MKTC_RTA_CMPLX_STATE_KICKED)
+#define	MKTC_RTA_CHECK_NEXT_SA_PROG				0xAD001F05
+MKTC_ST(MKTC_RTA_CHECK_NEXT_SA_PROG)
+#define MKTC_RTA_CORE_COMPLETED					0xAD001F06
+MKTC_ST(MKTC_RTA_CORE_COMPLETED)
+#define MKTC_RTA_DEBUG_SAS						0xAD001F07
+MKTC_ST(MKTC_RTA_DEBUG_SAS)
+#define MKTC_RTA_MTE_STATE_RESTORE_TASK			0xAD001F08
+MKTC_ST(MKTC_RTA_MTE_STATE_RESTORE_TASK)
+#define MKTC_RTA_SA_STATE_RESTORE_TASK			0xAD001F09
+MKTC_ST(MKTC_RTA_SA_STATE_RESTORE_TASK)
+#define MKTC_RESUMETA_END						0xAD001F0F
+MKTC_ST(MKTC_RESUMETA_END)
+
+#define MKTC_RENDERHALT							0xAD002000
+MKTC_ST(MKTC_RENDERHALT)
+#define MKTC_RH_CLEARFLAGS						0xAD002001
+MKTC_ST(MKTC_RH_CLEARFLAGS)
+#define MKTC_RH_CTRL_ADDR						0xAD002002
+MKTC_ST(MKTC_RH_CTRL_ADDR)
+#define MKTC_RH_RGN_ADDR						0xAD002003
+MKTC_ST(MKTC_RH_RGN_ADDR)
+#define MKTC_RH_EMPTY_TILE						0xAD002004
+MKTC_ST(MKTC_RH_EMPTY_TILE)
+#define MKTC_RH_EMPTY_LAST_TILE					0xAD002005
+MKTC_ST(MKTC_RH_EMPTY_LAST_TILE)
+#define MKTC_RH_3D_TIMEOUT						0xAD002006
+MKTC_ST(MKTC_RH_3D_TIMEOUT)
+#define MKTC_RH_NOT_EMPTY						0xAD002007
+MKTC_ST(MKTC_RH_NOT_EMPTY)
+#define MKTC_RH_OBJECT_COMPLETE					0xAD002008
+MKTC_ST(MKTC_RH_OBJECT_COMPLETE)
+#define MKTC_RH_STREAM_LINK						0xAD002009
+MKTC_ST(MKTC_RH_STREAM_LINK)
+#define MKTC_RH_OBJECT_INCOMPLETE				0xAD00200A
+MKTC_ST(MKTC_RH_OBJECT_INCOMPLETE)
+#define MKTC_RH_PRIM_MASK_PRESENT				0xAD00200B
+MKTC_ST(MKTC_RH_PRIM_MASK_PRESENT)
+#define MKTC_RH_BYTE_MASK_PRESENT				0xAD00200C
+MKTC_ST(MKTC_RH_BYTE_MASK_PRESENT)
+#define MKTC_RH_BYTE_MASK_ZERO					0xAD00200D
+MKTC_ST(MKTC_RH_BYTE_MASK_ZERO)
+#define MKTC_RH_PRIM_MASK_ZERO					0xAD00200E
+MKTC_ST(MKTC_RH_PRIM_MASK_ZERO)
+#define MKTC_RH_INVALIDATE_OBJECTS				0xAD00200F
+MKTC_ST(MKTC_RH_INVALIDATE_OBJECTS)
+#define MKTC_RH_OBJECTS_INVALIDATED				0xAD002010
+MKTC_ST(MKTC_RH_OBJECTS_INVALIDATED)
+#define MKTC_RH_DPM_RGN_PARSER_IDLE				0xAD002011
+MKTC_ST(MKTC_RH_DPM_RGN_PARSER_IDLE)
+#define MKTC_RH_NEXT_RGN_BASE					0xAD002012
+MKTC_ST(MKTC_RH_NEXT_RGN_BASE)
+#define MKTC_RH_OCC_EXIT						0xAD002013
+MKTC_ST(MKTC_RH_OCC_EXIT)
+#define MKTC_RH_STILL_RUNNING					0xAD002020
+MKTC_ST(MKTC_RH_STILL_RUNNING)
+#define MKTC_RH_CLEARMCI						0xAD002021
+MKTC_ST(MKTC_RH_CLEARMCI)
+#define MKTC_RH_EOR								0xAD002022
+MKTC_ST(MKTC_RH_EOR)
+#define MKTC_RENDERHALT_END						0xAD002030
+MKTC_ST(MKTC_RENDERHALT_END)
+
+#define	MKTC_FIND3D_POWERREQUEST				0xAD002100
+MKTC_ST(MKTC_FIND3D_POWERREQUEST)
+
+#define	MKTC_FIND2D_POWERREQUEST				0xAD002200
+MKTC_ST(MKTC_FIND2D_POWERREQUEST)
+
+#define	MKTC_UKERNEL_INIT						0xAD002300
+MKTC_ST(MKTC_UKERNEL_INIT)
+#define MKTC_UKERNEL_INIT_DCS_COMPLETE			0xAD002301
+MKTC_ST(MKTC_UKERNEL_INIT_DCS_COMPLETE)
+#define MKTC_UKERNEL_INIT_VDMKICK_COMPLETE		0xAD002303
+MKTC_ST(MKTC_UKERNEL_INIT_VDMKICK_COMPLETE)
+
+#define MKTC_KICKTRANSFERRENDER_START			0xAD002400
+MKTC_ST(MKTC_KICKTRANSFERRENDER_START)
+#define MKTC_KICKTRANSFERRENDER_ISP_START		0xAD002401
+MKTC_ST(MKTC_KICKTRANSFERRENDER_ISP_START)
+#define MKTC_KICKTRANSFERRENDER_END				0xAD002402
+MKTC_ST(MKTC_KICKTRANSFERRENDER_END)
+#define MKTC_DUMMYPROCTRANSFER					0xAD002403
+MKTC_ST(MKTC_DUMMYPROCTRANSFER)
+#define MKTC_KTR_TQFENCE						0xAD002404
+MKTC_ST(MKTC_KTR_TQFENCE)
+#define MKTC_KICKTRANSFERRENDER_PID				0xAD002405
+MKTC_ST(MKTC_KICKTRANSFERRENDER_PID)
+
+#define MKTC_HOSTKICK_CLEANUP_RT				0xAD002500
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_RT)
+#define MKTC_HOSTKICK_CLEANUP_RC				0xAD002501
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_RC)
+#define MKTC_HOSTKICK_CLEANUP_TC				0xAD002502
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_TC)
+#define MKTC_HOSTKICK_CLEANUP_2DC				0xAD002503
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_2DC)
+#define MKTC_HOSTKICK_CLEANUP_PB				0xAD002504
+MKTC_ST(MKTC_HOSTKICK_CLEANUP_PB)
+#define MKTC_HOSTKICK_GETMISCINFO				0xAD002505
+MKTC_ST(MKTC_HOSTKICK_GETMISCINFO)
+#define MKTC_HOSTKICK_DATABREAKPOINT			0xAD002506
+MKTC_ST(MKTC_HOSTKICK_DATABREAKPOINT)
+#define MKTC_HOSTKICK_SETHWPERFSTATUS			0xAD002507
+MKTC_ST(MKTC_HOSTKICK_SETHWPERFSTATUS)
+
+#define MKTC_ZEROPC								0xAD002600
+MKTC_ST(MKTC_ZEROPC)
+
+#define MKTC_ASSERT_FAIL						0xAD002700
+MKTC_ST(MKTC_ASSERT_FAIL)
+
+#define MKTC_SDLB_ILLEGAL						0xAD002800
+MKTC_ST(MKTC_SDLB_ILLEGAL)
+
+#define MKTC_SPMEVENT_OUTOFMEM					0xAD002901
+MKTC_ST(MKTC_SPMEVENT_OUTOFMEM)
+#define MKTC_SPMEVENT_TATERMINATE				0xAD002902
+MKTC_ST(MKTC_SPMEVENT_TATERMINATE)
+#define MKTC_SPMEVENT_END						0xAD002904
+MKTC_ST(MKTC_SPMEVENT_END)
+
+#define MKTC_SPMLB_OUTOFMEM						0xAD002981
+MKTC_ST(MKTC_SPMLB_OUTOFMEM)
+#define MKTC_SPMLB_TATERMINATE					0xAD002982
+MKTC_ST(MKTC_SPMLB_TATERMINATE)
+#define MKTC_SPMLB_SPMRENDERFINSHED				0xAD002983
+MKTC_ST(MKTC_SPMLB_SPMRENDERFINSHED)
+#define MKTC_SPMLB_END							0xAD002985
+MKTC_ST(MKTC_SPMLB_END)
+
+#define MKTC_SPM_CHECK_MT_DEADLOCK				0xAD002991
+MKTC_ST(MKTC_SPM_CHECK_MT_DEADLOCK)
+#define MKTC_SPM_CHECK_GLOBAL_DEADLOCK			0xAD002992
+MKTC_ST(MKTC_SPM_CHECK_GLOBAL_DEADLOCK)
+#define MKTC_SPM_RESERVE_ADDED					0xAD002993
+MKTC_ST(MKTC_SPM_RESERVE_ADDED)
+#define MKTC_SPM_FORCE_GLOBAL_OOM_FAILED		0xAD00299E
+MKTC_ST(MKTC_SPM_FORCE_GLOBAL_OOM_FAILED)
+#define MKTC_SPM_DEADLOCK_MEM_FAILED			0xAD00299F
+MKTC_ST(MKTC_SPM_DEADLOCK_MEM_FAILED)
+
+#define MKTC_IBC_ILLEGAL						0xAD002A00
+MKTC_ST(MKTC_IBC_ILLEGAL)
+
+#define MKTC_HWP_CLEARCOUNTERS					0xAD002B00
+MKTC_ST(MKTC_HWP_CLEARCOUNTERS)
+
+#define MKTC_TA_FRAMENUM						0xAD002C00
+MKTC_ST(MKTC_TA_FRAMENUM)
+#define MKTC_3D_FRAMENUM						0xAD002C01
+MKTC_ST(MKTC_3D_FRAMENUM)
+#define MKTC_SPM3D_FRAMENUM						0xAD002C02
+MKTC_ST(MKTC_SPM3D_FRAMENUM)
+
+#define MKTC_HKTA_RENDERCONTEXT					0xAD002D00
+MKTC_ST(MKTC_HKTA_RENDERCONTEXT)
+#define MKTC_IDLECORE_REFCOUNT_FAIL				0xAD002E00
+MKTC_ST(MKTC_IDLECORE_REFCOUNT_FAIL)
+
+#define MKTC_MCISTATE_NOT_CLEARED				0xAD002F00
+MKTC_ST(MKTC_MCISTATE_NOT_CLEARED)
+
+#define MKTC_LOWERED_TO_PDS_THRESHOLD				0xAD003000
+MKTC_ST(MKTC_LOWERED_TO_PDS_THRESHOLD)
+#define MKTC_REDUCE_MAX_VTX_PARTITIONS				0xAD003001
+MKTC_ST(MKTC_REDUCE_MAX_VTX_PARTITIONS)
+#define MKTC_KTAOVERRIDE_MAX_VTX_PARTITIONS			0xAD003002
+MKTC_ST(MKTC_KTAOVERRIDE_MAX_VTX_PARTITIONS)
+#define MKTC_KTANOOVERRIDE_MAX_VTX_PARTITIONS			0xAD003003
+MKTC_ST(MKTC_KTANOOVERRIDE_MAX_VTX_PARTITIONS)
+
+#define MKTC_IPRB_NORENDERDETAILS				0xAD003010
+MKTC_ST(MKTC_IPRB_NORENDERDETAILS)
+#define MKTC_IPRB_HAVERENDERDETAILS				0xAD003011
+MKTC_ST(MKTC_IPRB_HAVERENDERDETAILS)
+
+#define MKTC_RENDER_OUT_OF_ORDER				0xAD003020
+MKTC_ST(MKTC_RENDER_OUT_OF_ORDER)
+#define MKTC_RENDER_NOT_OUT_OF_ORDER			0xAD003021
+MKTC_ST(MKTC_RENDER_NOT_OUT_OF_ORDER)
+
+#define MKTC_ZLS_IDLE_BEGIN						0xAD003030
+MKTC_ST(MKTC_ZLS_IDLE_BEGIN)
+#define MKTC_ZLS_ISP_CLK_GATING_EN				0xAD003031
+MKTC_ST(MKTC_ZLS_ISP_CLK_GATING_EN)
+#define MKTC_ZLS_IDLE_END						0xAD003032
+MKTC_ST(MKTC_ZLS_IDLE_END)
+
+#endif /*  __SGX_UKERNEL_STATUS_CODES_H__ */
+
+/******************************************************************************
+ End of file (sgx_ukernel_status_codes.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/include/sgxinfo.h b/drivers/gpu/pvr/services4/include/sgxinfo.h
new file mode 100644
index 0000000..22a258d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/include/sgxinfo.h
@@ -0,0 +1,341 @@
+/*************************************************************************/ /*!
+@Title          sgx services structures/functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    inline functions/structures shared across UM and KM services components
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if !defined (__SGXINFO_H__)
+#define __SGXINFO_H__
+
+#include "sgxscript.h"
+#include "servicesint.h"
+#include "services.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+
+
+#define SGX_MAX_DEV_DATA			24
+#define	SGX_MAX_INIT_MEM_HANDLES	18
+
+
+typedef struct _SGX_BRIDGE_INFO_FOR_SRVINIT
+{
+	IMG_DEV_PHYADDR sPDDevPAddr;
+	PVRSRV_HEAP_INFO asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} SGX_BRIDGE_INFO_FOR_SRVINIT;
+
+
+typedef enum _SGXMKIF_CMD_TYPE_
+{
+	SGXMKIF_CMD_TA				= 0,
+	SGXMKIF_CMD_TRANSFER		= 1,
+	SGXMKIF_CMD_2D				= 2,
+	SGXMKIF_CMD_POWER			= 3,
+	SGXMKIF_CMD_CONTEXTSUSPEND	= 4,
+	SGXMKIF_CMD_CLEANUP			= 5,
+	SGXMKIF_CMD_GETMISCINFO		= 6,
+	SGXMKIF_CMD_PROCESS_QUEUES	= 7,
+	SGXMKIF_CMD_DATABREAKPOINT	= 8,
+	SGXMKIF_CMD_SETHWPERFSTATUS	= 9,
+ 	SGXMKIF_CMD_FLUSHPDCACHE	= 10,
+ 	SGXMKIF_CMD_MAX				= 11,
+
+	SGXMKIF_CMD_FORCE_I32   	= -1,
+
+} SGXMKIF_CMD_TYPE;
+
+typedef struct IMG_COMPAT _SGX_BRIDGE_INIT_INFO_
+{
+	IMG_HANDLE	hKernelCCBMemInfo;
+	IMG_HANDLE	hKernelCCBCtlMemInfo;
+	IMG_HANDLE	hKernelCCBEventKickerMemInfo;
+	IMG_HANDLE	hKernelSGXHostCtlMemInfo;
+	IMG_HANDLE	hKernelSGXTA3DCtlMemInfo;
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+	IMG_HANDLE	hKernelSGXPTLAWriteBackMemInfo;
+#endif
+	IMG_HANDLE	hKernelSGXMiscMemInfo;
+
+	IMG_UINT32	aui32HostKickAddr[SGXMKIF_CMD_MAX];
+	IMG_UINT32	ui32ClientBuildOptions;
+
+	SGX_INIT_SCRIPTS sScripts;
+
+	SGX_MISCINFO_STRUCT_SIZES	sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	IMG_HANDLE	hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+	IMG_HANDLE	hKernelHWPerfCBMemInfo;
+#endif
+	IMG_HANDLE	hKernelTASigBufferMemInfo;
+	IMG_HANDLE	hKernel3DSigBufferMemInfo;
+
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+	IMG_HANDLE hKernelClearClipWAVDMStreamMemInfo;
+	IMG_HANDLE hKernelClearClipWAIndexStreamMemInfo;
+	IMG_HANDLE hKernelClearClipWAPDSMemInfo;
+	IMG_HANDLE hKernelClearClipWAUSEMemInfo;
+	IMG_HANDLE hKernelClearClipWAParamMemInfo;
+	IMG_HANDLE hKernelClearClipWAPMPTMemInfo;
+	IMG_HANDLE hKernelClearClipWATPCMemInfo;
+	IMG_HANDLE hKernelClearClipWAPSGRgnHdrMemInfo;
+#endif
+
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+	defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+	IMG_HANDLE	hKernelVDMStateUpdateBufferMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	IMG_HANDLE	hKernelEDMStatusBufferMemInfo;
+#endif
+
+	IMG_UINT32 ui32EDMTaskReg0;
+	IMG_UINT32 ui32EDMTaskReg1;
+
+	IMG_UINT32 ui32ClkGateCtl;
+	IMG_UINT32 ui32ClkGateCtl2;
+	IMG_UINT32 ui32ClkGateStatusReg;
+	IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+	IMG_UINT32 ui32MasterClkGateStatusReg;
+	IMG_UINT32 ui32MasterClkGateStatusMask;
+	IMG_UINT32 ui32MasterClkGateStatus2Reg;
+	IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif /* SGX_FEATURE_MP */
+
+#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+	IMG_BOOL bDisableClockGating;
+#elif defined(USE_64BIT_COMPAT)
+	IMG_UINT32  ui32Padding;
+#endif
+	IMG_UINT32 ui32CacheControl;
+
+	IMG_UINT32	asInitDevData[SGX_MAX_DEV_DATA];
+	IMG_HANDLE	asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+} SGX_BRIDGE_INIT_INFO;
+
+
+typedef struct _SGX_DEVICE_SYNC_LIST_
+{
+	PSGXMKIF_HWDEVICE_SYNC_LIST	psHWDeviceSyncList;
+
+	IMG_HANDLE				hKernelHWSyncListMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	*psHWDeviceSyncListClientMemInfo;
+	PVRSRV_CLIENT_MEM_INFO	*psAccessResourceClientMemInfo;
+
+	volatile IMG_UINT32		*pui32Lock;
+
+	struct _SGX_DEVICE_SYNC_LIST_	*psNext;
+
+	/* Must be the last variable in the structure */
+	IMG_UINT32			ui32NumSyncObjects;
+	IMG_HANDLE			ahSyncHandles[1];
+} SGX_DEVICE_SYNC_LIST, *PSGX_DEVICE_SYNC_LIST;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_
+{
+	CTL_STATUS				sCtlStatus;
+	IMG_HANDLE				hKernelMemInfo;
+} SGX_INTERNEL_STATUS_UPDATE;
+
+typedef struct IMG_COMPAT _SGX_CCB_KICK_
+{
+	SGXMKIF_COMMAND		sCommand;
+	IMG_HANDLE	hCCBKernelMemInfo;
+
+	IMG_UINT32	ui32NumDstSyncObjects;
+	IMG_HANDLE	hKernelHWSyncListMemInfo;
+
+	/* DST syncs */
+	IMG_HANDLE	hDstSyncHandles;
+
+	IMG_UINT32	ui32NumTAStatusVals;
+	IMG_UINT32	ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+	SGX_INTERNEL_STATUS_UPDATE	asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+	SGX_INTERNEL_STATUS_UPDATE	as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+	IMG_HANDLE	ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+	IMG_HANDLE	ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+
+	IMG_BOOL	bFirstKickOrResume;
+#if defined(NO_HARDWARE) || defined(PDUMP)
+	IMG_BOOL	bTerminateOrAbort;
+#endif
+	IMG_BOOL	bLastInScene;
+
+	/* CCB offset of data structure associated with this kick */
+	IMG_UINT32	ui32CCBOffset;
+
+	/* SRC syncs */
+	IMG_UINT32	ui32NumSrcSyncs;
+	IMG_HANDLE	ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+
+	/* TA/3D dependency data */
+	IMG_BOOL	bTADependency;
+	IMG_HANDLE	hTA3DSyncInfo;
+
+	IMG_HANDLE	hTASyncInfo;
+	IMG_HANDLE	h3DSyncInfo;
+#if defined(PDUMP)
+	IMG_UINT32	ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+	IMG_UINT32	ui32WriteOpsPendingVal;
+#endif
+	IMG_HANDLE	hDevMemContext;
+	IMG_DEV_VIRTADDR	sHWRTDataSetDevAddr;
+	IMG_DEV_VIRTADDR	sHWRTDataDevAddr;
+	IMG_UINT32			ui32FrameNum;
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	IMG_BOOL	bIsFirstKick;
+#endif
+} SGX_CCB_KICK;
+
+
+/*!
+ ******************************************************************************
+ * shared client/kernel device information structure for SGX
+ *****************************************************************************/
+#define SGX_KERNEL_USE_CODE_BASE_INDEX		15
+
+
+/*!
+ ******************************************************************************
+ * Client device information structure for SGX
+ *****************************************************************************/
+typedef struct IMG_COMPAT _SGX_CLIENT_INFO_
+{
+	IMG_UINT32					ui32ProcessID;			/*!< ID of process controlling SGX device */
+	IMG_UINT32					asDevData[SGX_MAX_DEV_DATA];
+} SGX_CLIENT_INFO;
+
+/*!
+ ******************************************************************************
+ * Internal device information structure for SGX
+ *****************************************************************************/
+typedef struct IMG_COMPAT _SGX_INTERNAL_DEVINFO_
+{
+	IMG_HANDLE			hHostCtlKernelMemInfoHandle;
+	IMG_BOOL			bForcePTOff;
+} SGX_INTERNAL_DEVINFO;
+
+
+typedef struct _SGX_INTERNAL_DEVINFO_KM_
+{
+	IMG_UINT32			ui32Flags;
+	IMG_HANDLE			hHostCtlKernelMemInfoHandle;
+	IMG_BOOL			bForcePTOff;
+} SGX_INTERNAL_DEVINFO_KM;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct IMG_COMPAT _PVRSRV_TRANSFER_SGX_KICK_
+{
+	IMG_HANDLE		hCCBMemInfo;
+	IMG_UINT32		ui32SharedCmdCCBOffset;
+
+	IMG_DEV_VIRTADDR 	sHWTransferContextDevVAddr;
+
+	IMG_HANDLE		hTASyncInfo;
+	IMG_HANDLE		h3DSyncInfo;
+
+	IMG_UINT32		ui32NumSrcSync;
+	IMG_HANDLE		ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+	IMG_UINT32		ui32NumDstSync;
+	IMG_HANDLE		ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+	IMG_UINT32		ui32Flags;
+
+	IMG_UINT32		ui32PDumpFlags;
+#if defined(PDUMP)
+	IMG_UINT32		ui32CCBDumpWOff;
+#endif
+	IMG_HANDLE		hDevMemContext;
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	/* Android >JB MR1 doesn't use ahSrcSyncInfo for synchronization */
+	IMG_INT64			iFenceFd;
+#endif
+} PVRSRV_TRANSFER_SGX_KICK, *PPVRSRV_TRANSFER_SGX_KICK;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct IMG_COMPAT _PVRSRV_2D_SGX_KICK_
+{
+	IMG_HANDLE		hCCBMemInfo;
+	IMG_UINT32		ui32SharedCmdCCBOffset;
+
+	IMG_DEV_VIRTADDR 	sHW2DContextDevVAddr;
+
+	IMG_UINT32		ui32NumSrcSync;
+	IMG_HANDLE		ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+	/* need to be able to check reads and writes on dest, and update writes */
+	IMG_HANDLE 		hDstSyncInfo;
+
+	/* need to be able to check reads and writes on TA ops, and update writes */
+	IMG_HANDLE		hTASyncInfo;
+
+	/* need to be able to check reads and writes on 2D ops, and update writes */
+	IMG_HANDLE		h3DSyncInfo;
+
+	IMG_UINT32		ui32PDumpFlags;
+#if defined(PDUMP)
+	IMG_UINT32		ui32CCBDumpWOff;
+#endif
+	IMG_HANDLE		hDevMemContext;
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	/* Android >JB MR1 doesn't use ahSrcSyncInfo for synchronization */
+	IMG_INT			iFenceFd;
+#endif
+} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
+#endif	/* defined(SGX_FEATURE_2D_HARDWARE) */
+#endif	/* defined(TRANSFER_QUEUE) */
+
+
+#endif /* __SGXINFO_H__ */
+/******************************************************************************
+ End of file (sgxinfo.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
new file mode 100644
index 0000000..68a0f93
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_pvr_bridge.c
@@ -0,0 +1,5024 @@
+/*************************************************************************/ /*!
+@Title          PVR Common Bridge Module (kernel side)
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Receives calls from the user portion of services and
+                despatches them to functions in the kernel portion.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge_km.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "msvdx_bridge.h"
+#endif
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+#include "refcount.h"
+
+#include "pdump_km.h"
+#include "syscommon.h"
+
+#include "bridged_pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "bridged_sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "bridged_vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "bridged_msvdx_bridge.h"
+#endif
+
+#include "env_data.h"
+#include "ttrace.h"
+#include "ttrace_tokens.h"
+
+#if defined (__linux__) || defined(__QNXNTO__)
+#include "mmap.h"
+#endif
+
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include <linux/file.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
+#include <linux/sync.h>
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0))
+#include <../drivers/staging/android/sync.h>
+#else
+#include <../drivers/dma-buf/sync_debug.h>
+#endif
+#endif
+
+#include "srvkm.h"
+
+/* FIXME: we should include an OS specific header here to allow configuration of
+ * which functions should be excluded (like the shared srvclient bridge code)
+ * so that ports may choose to override certain things. */
+
+/* For the purpose of maintainability, it is intended that this file should not
+ * contain large amounts of OS specific #ifdefs. Headers are fine, and perhaps
+ * a few one liners, but for anything more, please find a way to add e.g.
+ * an osfunc.c abstraction or override the entire function in question within
+ * env,*,pvr_bridge_k.c
+ */
+
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+#if defined(PVR_SECURE_HANDLES)
+static IMG_BOOL abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static IMG_BOOL *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+#else
+static IMG_BOOL *pbSharedDeviceMemHeap = (IMG_BOOL*)IMG_NULL;
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+					IMG_UINT32 ui32BridgeID,
+					IMG_VOID *pvDest,
+					IMG_VOID *pvSrc,
+					IMG_UINT32 ui32Size)
+{
+	g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes+=ui32Size;
+	g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+=ui32Size;
+	return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+				  IMG_UINT32 ui32BridgeID,
+				  IMG_VOID *pvDest,
+				  IMG_VOID *pvSrc,
+				  IMG_UINT32 ui32Size)
+{
+	g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes+=ui32Size;
+	g_BridgeGlobalStats.ui32TotalCopyToUserBytes+=ui32Size;
+	return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+
+static IMG_INT
+PVRSRVEnumerateDevicesBW(IMG_UINT32 ui32BridgeID,
+						 IMG_VOID *psBridgeIn,
+						 PVRSRV_BRIDGE_OUT_ENUMDEVICE *psEnumDeviceOUT,
+						 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	psEnumDeviceOUT->eError =
+		PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+								 psEnumDeviceOUT->asDeviceIdentifier);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVAcquireDeviceDataBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *psAcquireDevInfoIN,
+						  PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *psAcquireDevInfoOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO);
+
+	psAcquireDevInfoOUT->eError =
+		PVRSRVAcquireDeviceDataKM(psAcquireDevInfoIN->uiDevIndex,
+								  psAcquireDevInfoIN->eDeviceType,
+								  &hDevCookieInt);
+	if(psAcquireDevInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/*
+	 * Handle is not allocated in batch mode, as there is no resource
+	 * allocation to undo if the handle allocation fails.
+	 */
+		psAcquireDevInfoOUT->eError =
+		PVRSRVAllocHandle(psPerProc->psHandleBase,
+						  &psAcquireDevInfoOUT->hDevCookie,
+						  hDevCookieInt,
+						  PVRSRV_HANDLE_TYPE_DEV_NODE,
+						  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *psCreateDevMemContextIN,
+							   PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *psCreateDevMemContextOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	IMG_UINT32 i;
+	IMG_BOOL bCreated;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
+
+	/*
+	 * We potentially need one handle for the device memory context,
+	 * and one handle for each client heap.
+	 */
+	NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1)
+
+	psCreateDevMemContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psCreateDevMemContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psCreateDevMemContextOUT->eError =
+		PVRSRVCreateDeviceMemContextKM(hDevCookieInt,
+									   psPerProc,
+									   &hDevMemContextInt,
+									   &psCreateDevMemContextOUT->ui32ClientHeapCount,
+									   &psCreateDevMemContextOUT->sHeapInfo[0],
+									   &bCreated,
+									   pbSharedDeviceMemHeap);
+
+	if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/*
+	 * Only allocate a handle if the device memory context was created.
+	 * If an existing context was returned, lookup the existing
+	 * handle.
+	 */
+	if(bCreated)
+	{
+		PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+						  &psCreateDevMemContextOUT->hDevMemContext,
+						  hDevMemContextInt,
+						  PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+						  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	}
+	else
+	{
+		psCreateDevMemContextOUT->eError =
+			PVRSRVFindHandle(psPerProc->psHandleBase,
+							 &psCreateDevMemContextOUT->hDevMemContext,
+							 hDevMemContextInt,
+							 PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+		if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	for(i = 0; i < psCreateDevMemContextOUT->ui32ClientHeapCount; i++)
+	{
+		IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+		if(abSharedDeviceMemHeap[i])
+#endif
+		{
+			/*
+			 * Heaps shared by everybody.  These heaps are not
+			 * created as part of the device memory context
+			 * creation, and exist for the lifetime of the
+			 * driver, hence, we use shared handles for these
+			 * heaps.
+			 */
+			PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+								psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+								PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+								PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+		}
+#if defined(PVR_SECURE_HANDLES)
+		else
+		{
+			/*
+			 * Heaps belonging to this context.  The handles for
+			 * these are made subhandles of the memory context
+			 * handle, so that they are automatically deallocated
+			 * when the memory context handle is deallocated.
+			 */
+			if(bCreated)
+			{
+				PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+									 psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+									 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+									 PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+									 psCreateDevMemContextOUT->hDevMemContext);
+			}
+			else
+			{
+				psCreateDevMemContextOUT->eError =
+					PVRSRVFindHandle(psPerProc->psHandleBase,
+									 &hDevMemHeapExt,
+									 psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+									 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+				if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+				{
+					return 0;
+				}
+			}
+		}
+#endif
+		psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc)
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+								PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *psDestroyDevMemContextIN,
+								PVRSRV_BRIDGE_RETURN *psRetOUT,
+								PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	IMG_BOOL bDestroyed;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psDestroyDevMemContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+						   psDestroyDevMemContextIN->hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVDestroyDeviceMemContextKM(hDevCookieInt, hDevMemContextInt, &bDestroyed);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(bDestroyed)
+	{
+		psRetOUT->eError =
+			PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psDestroyDevMemContextIN->hDevMemContext,
+								PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoIN,
+							   PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS)
+
+	psGetDevMemHeapInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psGetDevMemHeapInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDevMemHeapInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+						   psGetDevMemHeapInfoIN->hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDevMemHeapInfoOUT->eError =
+		PVRSRVGetDeviceMemHeapInfoKM(hDevCookieInt,
+									   hDevMemContextInt,
+									   &psGetDevMemHeapInfoOUT->ui32ClientHeapCount,
+									   &psGetDevMemHeapInfoOUT->sHeapInfo[0],
+									   pbSharedDeviceMemHeap);
+
+	if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	for(i = 0; i < psGetDevMemHeapInfoOUT->ui32ClientHeapCount; i++)
+	{
+		IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+		if(abSharedDeviceMemHeap[i])
+#endif
+		{
+			/*
+			 * Heaps shared by everybody.  These heaps are not
+			 * created as part of the device memory context
+			 * creation, and exist for the lifetime of the
+			 * driver, hence, we use shared handles for these
+			 * heaps.
+			 */
+			PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+							  psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+							  PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+							  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+		}
+#if defined(PVR_SECURE_HANDLES)
+		else
+		{
+			/*
+			 * Heaps belonging to this context.  The handles for
+			 * these are made subhandles of the memory context
+			 * handle, so that they are automatically deallocated
+			 * when the memory context handle is deallocated.
+			 */
+			psGetDevMemHeapInfoOUT->eError =
+				PVRSRVFindHandle(psPerProc->psHandleBase,
+								 &hDevMemHeapExt,
+								 psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+								 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+			if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+			{
+				return 0;
+			}
+		}
+#endif
+		psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc)
+
+	return 0;
+}
+
+
+#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+/* customised version */
+IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+					   PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+					   PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemHeapInt;
+	IMG_UINT32 ui32ShareIndex;
+	IMG_BOOL bUseShareMemWorkaround;
+	IMG_BOOL *pabMapChunk = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2)
+
+	/* Do same sanity checking */
+	if (psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_SPARSE)
+	{
+		if (psAllocDeviceMemIN->ui32NumPhysChunks > psAllocDeviceMemIN->ui32NumVirtChunks)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: more physical chunks then virtual space"));
+			psAllocDeviceMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+			return 0;
+		}
+
+		if (psAllocDeviceMemIN->hMapChunk == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Called in sparse mapping mode but without MapChunk array"));
+			psAllocDeviceMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+			return 0;
+		}
+	}
+
+	psAllocDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psAllocDeviceMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psAllocDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemHeapInt,
+						   psAllocDeviceMemIN->hDevMemHeap,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+
+	if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* Memory sharing workaround, version 2 */
+
+	bUseShareMemWorkaround = ((psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_XPROC) != 0) ? IMG_TRUE : IMG_FALSE;
+	ui32ShareIndex = 7654321; /* stops MSVC compiler warning */
+
+	if (bUseShareMemWorkaround)
+	{
+		/* allocate a shared-surface ID, prior to the call to AllocDeviceMem */
+		/* We could plumb in an extra argument, but for now, we'll keep the
+		   shared-surface ID as a piece of global state, and rely upon the
+		   bridge mutex to make it safe for us */
+
+		psAllocDeviceMemOUT->eError =
+			BM_XProcWorkaroundFindNewBufferAndSetShareIndex(&ui32ShareIndex);
+		if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	/* Check access to private data, if provided */
+	if(psAllocDeviceMemIN->hPrivData)
+	{
+		if(!OSAccessOK(PVR_VERIFY_READ,
+					   psAllocDeviceMemIN->hPrivData,
+					   psAllocDeviceMemIN->ui32PrivDataLength))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Access check failed for pvPrivData"));
+			return -EFAULT;
+		}
+	}
+
+	if (psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_SPARSE)
+	{
+		/* Check access to the sparse mapping table, if provided */
+		if(!OSAccessOK(PVR_VERIFY_READ,
+					   psAllocDeviceMemIN->hMapChunk,
+					   psAllocDeviceMemIN->ui32NumVirtChunks))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Access check failed for pabMapChunk"));
+			return -EFAULT;
+		}
+
+		psAllocDeviceMemOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+												 sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks,
+												 (IMG_VOID **) &pabMapChunk,
+												 0,
+												 "MapChunk kernel copy");
+		if (psAllocDeviceMemOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+
+		psAllocDeviceMemOUT->eError = OSCopyFromUser(psPerProc,
+													 pabMapChunk,
+													 psAllocDeviceMemIN->hMapChunk,
+													 sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks);
+		if (psAllocDeviceMemOUT->eError != PVRSRV_OK)
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks,
+					  pabMapChunk,
+					  0);
+			return 0;
+		}
+	}
+
+
+	psAllocDeviceMemOUT->eError =
+		PVRSRVAllocDeviceMemKM(hDevCookieInt,
+							   psPerProc,
+							   hDevMemHeapInt,
+							   psAllocDeviceMemIN->ui32Attribs,
+							   psAllocDeviceMemIN->uSize,
+							   psAllocDeviceMemIN->uAlignment,
+							   psAllocDeviceMemIN->hPrivData,
+							   psAllocDeviceMemIN->ui32PrivDataLength,
+							   psAllocDeviceMemIN->ui32ChunkSize,
+							   psAllocDeviceMemIN->ui32NumVirtChunks,
+							   psAllocDeviceMemIN->ui32NumPhysChunks,
+							   pabMapChunk,
+							   &psMemInfo,
+							   "" /*FIXME: add something meaningful*/);
+	if (psAllocDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: PVRSRVAllocDeviceMemKM failed with eError = %d", psAllocDeviceMemOUT->eError));
+		return -ENOMEM;
+	}
+
+	if (bUseShareMemWorkaround)
+	{
+        PVR_ASSERT(ui32ShareIndex != 7654321);
+		BM_XProcWorkaroundUnsetShareIndex(ui32ShareIndex);
+	}
+
+	if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psMemInfo->sShareMemWorkaround.bInUse = bUseShareMemWorkaround;
+	if (bUseShareMemWorkaround)
+	{
+		PVR_ASSERT(ui32ShareIndex != 7654321);
+		psMemInfo->sShareMemWorkaround.ui32ShareIndex = ui32ShareIndex;
+		psMemInfo->sShareMemWorkaround.hDevCookieInt = hDevCookieInt;
+		psMemInfo->sShareMemWorkaround.ui32OrigReqAttribs = psAllocDeviceMemIN->ui32Attribs;
+		psMemInfo->sShareMemWorkaround.ui32OrigReqSize = (IMG_UINT32)psAllocDeviceMemIN->uSize;
+		psMemInfo->sShareMemWorkaround.ui32OrigReqAlignment = (IMG_UINT32)psAllocDeviceMemIN->uAlignment;
+	}
+
+	OSMemSet(&psAllocDeviceMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+	psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+			psMemInfo->pvLinAddrKM;
+
+#if defined (__linux__)
+	psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = 0;
+#else
+	psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = psMemInfo->pvLinAddrKM;
+#endif
+	psAllocDeviceMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+	psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+	psAllocDeviceMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
+	psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	psAllocDeviceMemOUT->sClientMemInfo.sDevMemTimingStats.sDevMemMapTimes.ui32TimeToDevMap = psMemInfo->ui32TimeToDevMap;
+#endif
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+	if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+		/* signal no syncinfo */
+		OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
+				 0,
+				 sizeof (PVRSRV_CLIENT_SYNC_INFO));
+		psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+	}
+	else
+	{
+		/* and setup the sync info */
+
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+		psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
+			psMemInfo->psKernelSyncInfo->psSyncData;
+		psAllocDeviceMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+		psAllocDeviceMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+		psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo =
+			psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							 &psAllocDeviceMemOUT->sClientSyncInfo.hKernelSyncInfo,
+							 psMemInfo->psKernelSyncInfo,
+							 PVRSRV_HANDLE_TYPE_SYNC_INFO,
+							 PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+							 psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+
+		psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
+			&psAllocDeviceMemOUT->sClientSyncInfo;
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc)
+
+	return 0;
+}
+
+#endif /* OS_PVRSRV_ALLOC_DEVICE_MEM_BW */
+
+static IMG_INT
+PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_FREEDEVICEMEM *psFreeDeviceMemIN,
+					  PVRSRV_BRIDGE_OUT_FREEDEVICEMEM *psFreeDeviceMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	IMG_UINT32 ui32TimeToDevUnmap;
+#endif
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
+
+	psFreeDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psFreeDeviceMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psFreeDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psFreeDeviceMemOUT->eError =
+        PVRSRVLookupHandle(psPerProc->psHandleBase,
+                           (IMG_PVOID *)&psKernelMemInfo,
+						   psFreeDeviceMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psFreeDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	psKernelMemInfo->pui32TimeToDevUnmap = &ui32TimeToDevUnmap;
+#endif
+
+	psFreeDeviceMemOUT->eError = PVRSRVFreeDeviceMemKM(hDevCookieInt, psKernelMemInfo);
+
+	if(psFreeDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	psFreeDeviceMemOUT->ui32TimeToDevUnmap = ui32TimeToDevUnmap;
+#endif
+
+	psFreeDeviceMemOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psFreeDeviceMemIN->hKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM *psExportDeviceMemIN,
+					  PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	PVR_ASSERT(ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM) ||
+			   ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2));
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	/* find the device cookie */
+	psExportDeviceMemOUT->eError =
+        PVRSRVLookupHandle(psPerProc->psHandleBase,
+                           &hDevCookieInt,
+						   psExportDeviceMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find devcookie"));
+		return 0;
+	}
+
+	/* find the kernel meminfo from the process handle list */
+	psExportDeviceMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_PVOID *)&psKernelMemInfo,
+						   psExportDeviceMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find kernel meminfo"));
+		return 0;
+	}
+
+	/* see if it's already exported */
+	psExportDeviceMemOUT->eError =
+		PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+							 &psExportDeviceMemOUT->hMemInfo,
+							 psKernelMemInfo,
+							 PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psExportDeviceMemOUT->eError == PVRSRV_OK)
+	{
+		/* it's already exported */
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
+		return 0;
+	}
+
+	/* export the allocation */
+	psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+													&psExportDeviceMemOUT->hMemInfo,
+													psKernelMemInfo,
+													PVRSRV_HANDLE_TYPE_MEM_INFO,
+													PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	if (psExportDeviceMemOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: failed to allocate handle from global handle list"));
+		return 0;
+	}
+
+	/* mark the meminfo as 'exported' */
+	psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN,
+							 PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDevMemOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psSrcKernelMemInfo = IMG_NULL;
+	PVRSRV_KERNEL_MEM_INFO	*psDstKernelMemInfo = IMG_NULL;
+	IMG_HANDLE				hDstDevMemHeap = IMG_NULL;
+
+	PVR_ASSERT(ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEV_MEMORY) ||
+			   ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEV_MEMORY_2));
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2)
+
+	/* lookup srcmeminfo handle */
+	psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+												(IMG_VOID**)&psSrcKernelMemInfo,
+												psMapDevMemIN->hKernelMemInfo,
+												PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psMapDevMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* lookup dev mem heap handle */
+	psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+												&hDstDevMemHeap,
+												psMapDevMemIN->hDstDevMemHeap,
+												PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+	if(psMapDevMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* check for workaround */
+	if (psSrcKernelMemInfo->sShareMemWorkaround.bInUse)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "using the mem wrap workaround."));
+
+		/* Ensure we get the same ID for this allocation, such that it
+		   inherits the same physical block.  Rather than add a lot of
+		   plumbing to several APIs, we call into buffer manager directly
+		   to set "global" state.  This works only if we make
+		   this allocation while holding the bridge mutex and don't
+		   make any other allocations (because the state persists and
+		   would affect other device memory allocations too).  It is
+		   important that we bracket the PVRSRVAllocDeviceMemKM() call
+		   with this Set/Unset pair. */
+		psMapDevMemOUT->eError = BM_XProcWorkaroundSetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+		if(psMapDevMemOUT->eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryBW(): failed to recycle shared buffer"));
+			return 0;
+		}
+
+		psMapDevMemOUT->eError =
+			PVRSRVAllocDeviceMemKM(psSrcKernelMemInfo->sShareMemWorkaround.hDevCookieInt,
+								   psPerProc,
+								   hDstDevMemHeap,
+								   psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAttribs | PVRSRV_MEM_NO_SYNCOBJ,
+								   psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqSize,
+								   psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAlignment,
+								   IMG_NULL,
+								   0,
+								   /* FIXME: Do we need to be able to export sparse memory? */
+								   0,0,0,IMG_NULL,	/* No sparse mapping data */
+								   &psDstKernelMemInfo,
+								   "" /*FIXME: add something meaningful*/);
+		/* counterpart of the above "SetShareIndex".  NB: this must be
+		   done in both the success and failure paths of the
+		   AllocDeviceMemKM() call */
+		BM_XProcWorkaroundUnsetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+		if(psMapDevMemOUT->eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryBW: Failed to create allocation for cross-process memory map"));
+			return 0;
+		}
+
+		if(psSrcKernelMemInfo->psKernelSyncInfo)
+		{
+			PVRSRVKernelSyncInfoIncRef(psSrcKernelMemInfo->psKernelSyncInfo, psSrcKernelMemInfo);
+		}
+
+		psDstKernelMemInfo->psKernelSyncInfo = psSrcKernelMemInfo->psKernelSyncInfo;
+	}
+	else
+	{
+		/* map the meminfo to the target heap and memory context */
+		psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
+														 psSrcKernelMemInfo,
+														 hDstDevMemHeap,
+														 &psDstKernelMemInfo);
+		if(psMapDevMemOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	/* copy the workaround info */
+	psDstKernelMemInfo->sShareMemWorkaround = psSrcKernelMemInfo->sShareMemWorkaround;
+
+	OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
+			 0,
+			 sizeof(psMapDevMemOUT->sDstClientMemInfo));
+	OSMemSet(&psMapDevMemOUT->sDstClientSyncInfo,
+			 0,
+			 sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+	psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+			psDstKernelMemInfo->pvLinAddrKM;
+
+	psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = 0;
+	psMapDevMemOUT->sDstClientMemInfo.sDevVAddr = psDstKernelMemInfo->sDevVAddr;
+	psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
+    psMapDevMemOUT->sDstClientMemInfo.uAllocSize = psDstKernelMemInfo->uAllocSize;
+	psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+
+	/* allocate handle to the DST kernel meminfo */
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
+					  psDstKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+
+	/* and setup the sync info */
+	if(psDstKernelMemInfo->psKernelSyncInfo)
+	{
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+		psMapDevMemOUT->sDstClientSyncInfo.psSyncData =
+			psDstKernelMemInfo->psKernelSyncInfo->psSyncData;
+		psMapDevMemOUT->sDstClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+		psMapDevMemOUT->sDstClientSyncInfo.sReadOps2CompleteDevVAddr =
+			psDstKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+		psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo =
+			psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+
+		psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
+		/*
+		 * The sync info is associated with the device buffer,
+		 * and not allocated here.  It isn't exported when created,
+		 * hence the handle allocation rather than a lookup.
+		 */
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
+					  psDstKernelMemInfo->psKernelSyncInfo,
+					  PVRSRV_HANDLE_TYPE_SYNC_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc)
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY *psUnmapDevMemIN,
+							 PVRSRV_BRIDGE_RETURN *psRetOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psKernelMemInfo = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEV_MEMORY);
+
+	psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+											(IMG_VOID**)&psKernelMemInfo,
+											psUnmapDevMemIN->hKernelMemInfo,
+											PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+	{
+		psRetOUT->eError = PVRSRVFreeDeviceMemKM(psKernelMemInfo->sShareMemWorkaround.hDevCookieInt, psKernelMemInfo);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVUnmapDeviceMemoryBW: internal error, should expect FreeDeviceMem to fail"));
+			return 0;
+		}
+	}
+	else
+	{
+		psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psUnmapDevMemIN->hKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+static IMG_INT
+PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *psMapDevClassMemIN,
+							 PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psMapDevClassMemOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+	IMG_HANDLE hOSMapInfo;
+	IMG_HANDLE hDeviceClassBufferInt;
+	IMG_HANDLE hDevMemContextInt;
+	PVRSRV_HANDLE_TYPE eHandleType;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2)
+
+	/*
+	 * The buffer to be mapped can belong to a 3rd party display or
+	 * buffer driver, and we don't know which type we have at this
+	 * point.
+	 */
+	psMapDevClassMemOUT->eError =
+        PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+								  &hDeviceClassBufferInt,
+								  &eHandleType,
+								  psMapDevClassMemIN->hDeviceClassBuffer);
+
+	if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* get the device memory context */
+	psMapDevClassMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+				   &hDevMemContextInt,
+				   psMapDevClassMemIN->hDevMemContext,
+				   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* Having looked up the handle, now check its type */
+	switch(eHandleType)
+	{
+#if defined(PVR_SECURE_HANDLES)
+		case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+		case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+#else
+		case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+			break;
+		default:
+			psMapDevClassMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+			return 0;
+	}
+
+	psMapDevClassMemOUT->eError =
+		PVRSRVMapDeviceClassMemoryKM(psPerProc,
+									 hDevMemContextInt,
+									 hDeviceClassBufferInt,
+									 &psMemInfo,
+									 &hOSMapInfo);
+	if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	OSMemSet(&psMapDevClassMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psMapDevClassMemOUT->sClientMemInfo));
+	OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo,
+			 0,
+			 sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+	psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+			psMemInfo->pvLinAddrKM;
+
+	psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psMapDevClassMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+	psMapDevClassMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+    psMapDevClassMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
+	psMapDevClassMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+					  psMapDevClassMemIN->hDeviceClassBuffer);
+
+	psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+	/* and setup the sync info */
+	if(psMemInfo->psKernelSyncInfo)
+	{
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+		psMapDevClassMemOUT->sClientSyncInfo.psSyncData =
+			psMemInfo->psKernelSyncInfo->psSyncData;
+		psMapDevClassMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+		psMapDevClassMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+			psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+		psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo =
+			psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+
+		psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
+		/*
+		 * The sync info is associated with the device buffer,
+		 * and not allocated here.  It isn't exported when
+		 * created, hence the handle allocation rather than a
+		 * lookup.
+		 */
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+						  &psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
+						  psMemInfo->psKernelSyncInfo,
+						  PVRSRV_HANDLE_TYPE_SYNC_INFO,
+						  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+						  psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo);
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc)
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *psUnmapDevClassMemIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+						   psUnmapDevClassMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVUnmapDeviceClassMemoryKM(pvKernelMemInfo);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psUnmapDevClassMemIN->hKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+
+#if defined(OS_PVRSRV_WRAP_EXT_MEM_BW)
+IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+					  PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else /* OS_PVRSRV_WRAP_EXT_MEM_BW */
+static IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+					  PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt;
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+	IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+        IMG_UINT32 ui32PageTableSize = 0;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2)
+
+	/*
+	 * FIXME: This needs reworking - don't use the user supplied page
+	 * table list, get the list from the OS.
+	 */
+	psWrapExtMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psWrapExtMemIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psWrapExtMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* get the device memory context */
+	psWrapExtMemOUT->eError =
+	PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+				   psWrapExtMemIN->hDevMemContext,
+				   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psWrapExtMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(psWrapExtMemIN->ui32NumPageTableEntries)
+	{
+		ui32PageTableSize = psWrapExtMemIN->ui32NumPageTableEntries
+						* sizeof(IMG_SYS_PHYADDR);
+
+		ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+				  OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32PageTableSize,
+				  (IMG_VOID **)&psSysPAddr, 0,
+				  "Page Table"));
+
+		if(CopyFromUserWrapper(psPerProc,
+							   ui32BridgeID,
+							   psSysPAddr,
+							   psWrapExtMemIN->psSysPAddr,
+							   ui32PageTableSize) != PVRSRV_OK)
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 	ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
+			/*not nulling pointer, out of scope*/
+			return -EFAULT;
+		}
+	}
+
+	psWrapExtMemOUT->eError =
+		PVRSRVWrapExtMemoryKM(hDevCookieInt,
+							  psPerProc,
+							  hDevMemContextInt,
+							  psWrapExtMemIN->uByteSize,
+							  psWrapExtMemIN->uPageOffset,
+							  psWrapExtMemIN->bPhysContig,
+							  psSysPAddr,
+							  psWrapExtMemIN->pvLinAddr,
+							  psWrapExtMemIN->ui32Flags,
+							  &psMemInfo);
+
+	if(psWrapExtMemIN->ui32NumPageTableEntries)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  ui32PageTableSize,
+			  (IMG_VOID *)psSysPAddr, 0);
+		/*not nulling pointer, out of scope*/
+	}
+
+	if(psWrapExtMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+			psMemInfo->pvLinAddrKM;
+
+	/* setup the mem info */
+	psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+	psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+    psWrapExtMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
+	psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+	/* setup the sync info */
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+	psWrapExtMemOUT->sClientSyncInfo.psSyncData =
+		psMemInfo->psKernelSyncInfo->psSyncData;
+	psWrapExtMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+		psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+	psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+		psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+	psWrapExtMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+		psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+	psWrapExtMemOUT->sClientSyncInfo.hMappingInfo =
+		psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+
+	psWrapExtMemOUT->sClientMemInfo.psClientSyncInfo = &psWrapExtMemOUT->sClientSyncInfo;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psWrapExtMemOUT->sClientSyncInfo.hKernelSyncInfo,
+					  (IMG_HANDLE)psMemInfo->psKernelSyncInfo,
+					  PVRSRV_HANDLE_TYPE_SYNC_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+					  psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc)
+
+	return 0;
+}
+#endif /* OS_PVRSRV_WRAP_EXT_MEM_BW */
+
+static IMG_INT
+PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+						PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY *psUnwrapExtMemIN,
+						PVRSRV_BRIDGE_RETURN *psRetOUT,
+						PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvMemInfo,
+						   psUnwrapExtMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVUnwrapExtMemoryKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+						   psUnwrapExtMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+
+#if defined(SUPPORT_ION)
+static IMG_INT
+PVRSRVMapIonHandleBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_MAP_ION_HANDLE *psMapIonIN,
+					   PVRSRV_BRIDGE_OUT_MAP_ION_HANDLE *psMapIonOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+	IMG_UINT64 ui64Stamp;
+
+	psMapIonOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+											 &psMapIonIN->hDevCookie,
+											 psMapIonIN->hDevCookie,
+											 PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if (psMapIonOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup device node handle", __FUNCTION__));
+		return 0;
+	}
+
+	psMapIonOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+											 &psMapIonIN->hDevMemHeap,
+											 psMapIonIN->hDevMemHeap,
+											 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+	if (psMapIonOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup memory context handle", __FUNCTION__));
+		return 0;
+	}
+
+	psMapIonOUT->eError = PVRSRVMapIonHandleKM(psPerProc,
+											   psMapIonIN->hDevCookie,
+											   psMapIonIN->hDevMemHeap,
+											   psMapIonIN->ui32NumFDs,
+											   psMapIonIN->ai32BufferFDs,
+											   psMapIonIN->ui32Attribs,
+											   psMapIonIN->ui32ChunkCount,
+											   psMapIonIN->auiOffset,
+											   psMapIonIN->auiSize,
+											   &psMapIonOUT->uiIonBufferSize,
+											   &psKernelMemInfo,
+											   &ui64Stamp);
+	if (psMapIonOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map ion handle", __FUNCTION__));
+		return 0;
+	}
+
+	OSMemSet(&psMapIonOUT->sClientMemInfo,
+			 0,
+			 sizeof(psMapIonOUT->sClientMemInfo));
+
+	psMapIonOUT->sClientMemInfo.pvLinAddrKM =
+			psKernelMemInfo->pvLinAddrKM;
+
+	psMapIonOUT->sClientMemInfo.pvLinAddr = 0;
+	psMapIonOUT->sClientMemInfo.sDevVAddr = psKernelMemInfo->sDevVAddr;
+	psMapIonOUT->sClientMemInfo.ui32Flags = psKernelMemInfo->ui32Flags;
+	psMapIonOUT->sClientMemInfo.uAllocSize = psKernelMemInfo->uAllocSize;
+
+	/* No mapping info, we map through ion */
+	psMapIonOUT->sClientMemInfo.hMappingInfo = IMG_NULL;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+	psMapIonOUT->sClientMemInfo.ui64Stamp = ui64Stamp;
+#endif
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+						&psMapIonOUT->sClientMemInfo.hKernelMemInfo,
+						psKernelMemInfo,
+						PVRSRV_HANDLE_TYPE_MEM_INFO,
+						PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	if(psMapIonIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+		/* signal no syncinfo */
+		OSMemSet(&psMapIonOUT->sClientSyncInfo,
+				 0,
+				 sizeof (PVRSRV_CLIENT_SYNC_INFO));
+		psMapIonOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+	}
+	else
+	{
+		/* and setup the sync info */
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+		psMapIonOUT->sClientSyncInfo.psSyncData =
+			psKernelMemInfo->psKernelSyncInfo->psSyncData;
+		psMapIonOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapIonOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+		psMapIonOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+		psMapIonOUT->sClientSyncInfo.hMappingInfo =
+			psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							   &psMapIonOUT->sClientSyncInfo.hKernelSyncInfo,
+							   psKernelMemInfo->psKernelSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO,
+							   PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+							   psMapIonOUT->sClientMemInfo.hKernelMemInfo);
+
+		psMapIonOUT->sClientMemInfo.psClientSyncInfo =
+			&psMapIonOUT->sClientSyncInfo;
+	}
+	return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapIonHandleBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_UNMAP_ION_HANDLE *psUnmapIonIN,
+					   PVRSRV_BRIDGE_RETURN *psUnmapIonOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_ION_HANDLE);
+
+	psUnmapIonOUT->eError =
+        PVRSRVLookupHandle(psPerProc->psHandleBase,
+                           &pvKernelMemInfo,
+						   psUnmapIonIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psUnmapIonOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psUnmapIonOUT->eError = PVRSRVUnmapIonHandleKM(pvKernelMemInfo);
+
+	if(psUnmapIonOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psUnmapIonOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psUnmapIonIN->hKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+#endif	/* SUPPORT_ION */
+
+#if defined(SUPPORT_DMABUF)
+static IMG_INT
+PVRSRVMapDmaBufBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_MAP_DMABUF *psMapDmaBufIN,
+					   PVRSRV_BRIDGE_OUT_MAP_DMABUF *psMapDmaBufOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO  *psKernelMemInfo;
+	IMG_UINT64 ui64Stamp;
+
+	psMapDmaBufOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+											 &psMapDmaBufIN->hDevCookie,
+											 psMapDmaBufIN->hDevCookie,
+											 PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if (psMapDmaBufOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup device node handle", __FUNCTION__));
+		return 0;
+	}
+
+	psMapDmaBufOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+											 &psMapDmaBufIN->hDevMemHeap,
+											 psMapDmaBufIN->hDevMemHeap,
+											 PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+	if (psMapDmaBufOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup memory context handle", __FUNCTION__));
+		return 0;
+	}
+
+	psMapDmaBufOUT->eError = PVRSRVMapDmaBufKM(psPerProc,
+											   psMapDmaBufIN->hDevCookie,
+											   psMapDmaBufIN->hDevMemHeap,
+											   psMapDmaBufIN->ui32Attribs,
+											   psMapDmaBufIN->i32FD,
+											   psMapDmaBufIN->uiOffset,
+											   psMapDmaBufIN->uiSize,
+											   &psKernelMemInfo,
+											   &psMapDmaBufOUT->uiSize,
+											   &psMapDmaBufOUT->uiOffset,
+											   &ui64Stamp);
+	if (psMapDmaBufOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map dma-buf handle", __FUNCTION__));
+		return 0;
+	}
+
+	OSMemSet(&psMapDmaBufOUT->sClientMemInfo,
+			 0,
+			 sizeof(psMapDmaBufOUT->sClientMemInfo));
+
+	psMapDmaBufOUT->sClientMemInfo.pvLinAddrKM =
+			psKernelMemInfo->pvLinAddrKM;
+
+	psMapDmaBufOUT->sClientMemInfo.pvLinAddr = 0;
+	psMapDmaBufOUT->sClientMemInfo.sDevVAddr = psKernelMemInfo->sDevVAddr;
+	psMapDmaBufOUT->sClientMemInfo.ui32Flags = psKernelMemInfo->ui32Flags;
+	psMapDmaBufOUT->sClientMemInfo.uAllocSize = psKernelMemInfo->uAllocSize;
+
+	/* No mapping info, we map through dma_buf */
+	psMapDmaBufOUT->sClientMemInfo.hMappingInfo = IMG_NULL;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+	psMapDmaBufOUT->sClientMemInfo.ui64Stamp = ui64Stamp;
+#endif
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+						&psMapDmaBufOUT->sClientMemInfo.hKernelMemInfo,
+						psKernelMemInfo,
+						PVRSRV_HANDLE_TYPE_MEM_INFO,
+						PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	if(psMapDmaBufIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+		/* signal no syncinfo */
+		OSMemSet(&psMapDmaBufOUT->sClientSyncInfo,
+				 0,
+				 sizeof (PVRSRV_CLIENT_SYNC_INFO));
+		psMapDmaBufOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+	}
+	else
+	{
+		/* and setup the sync info */
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+		psMapDmaBufOUT->sClientSyncInfo.psSyncData =
+			psKernelMemInfo->psKernelSyncInfo->psSyncData;
+		psMapDmaBufOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapDmaBufOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+		psMapDmaBufOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+		psMapDmaBufOUT->sClientSyncInfo.hMappingInfo =
+			psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+
+		/*
+		 * If the DMA Buffer is imported into the same process that
+		 * exported it, there will be two handles for the same sync
+		 * info, hence the PVRSRV_HANDLE_ALLOC_FLAG_MULTI flag.
+		 */
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							   &psMapDmaBufOUT->sClientSyncInfo.hKernelSyncInfo,
+							   psKernelMemInfo->psKernelSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO,
+							   PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+							   psMapDmaBufOUT->sClientMemInfo.hKernelMemInfo);
+
+		psMapDmaBufOUT->sClientMemInfo.psClientSyncInfo =
+			&psMapDmaBufOUT->sClientSyncInfo;
+	}
+	return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapDmaBufBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_UNMAP_DMABUF *psUnmapDmaBufIN,
+					   PVRSRV_BRIDGE_RETURN *psUnmapDmaBufOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DMABUF);
+
+	psUnmapDmaBufOUT->eError =
+        PVRSRVLookupHandle(psPerProc->psHandleBase,
+                           &pvKernelMemInfo,
+						   psUnmapDmaBufIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psUnmapDmaBufOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psUnmapDmaBufOUT->eError = PVRSRVUnmapDmaBufKM(pvKernelMemInfo);
+
+	if(psUnmapDmaBufOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psUnmapDmaBufOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psUnmapDmaBufIN->hKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	return 0;
+}
+#endif	/* SUPPORT_DMABUF */
+
+static IMG_INT
+PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+						 PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
+						 PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *psGetFreeDeviceMemOUT,
+						 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psGetFreeDeviceMemOUT->eError =
+		PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+								 &psGetFreeDeviceMemOUT->uTotal,
+								 &psGetFreeDeviceMemOUT->uFree,
+								 &psGetFreeDeviceMemOUT->uLargestBlock);
+
+	return 0;
+}
+
+static IMG_INT
+PVRMMapOSMemHandleToMMapDataBW(IMG_UINT32 ui32BridgeID,
+								  PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *psMMapDataIN,
+								  PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *psMMapDataOUT,
+								  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+#if defined (__linux__) || defined (__QNXNTO__)
+	psMMapDataOUT->eError =
+		PVRMMapOSMemHandleToMMapData(psPerProc,
+										psMMapDataIN->hMHandle,
+										&psMMapDataOUT->uiMMapOffset,
+										&psMMapDataOUT->uiByteOffset,
+										&psMMapDataOUT->uiRealByteSize,
+										&psMMapDataOUT->uiUserVAddr);
+#else
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+	psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+	return 0;
+}
+
+
+static IMG_INT
+PVRMMapReleaseMMapDataBW(IMG_UINT32 ui32BridgeID,
+								  PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA *psMMapDataIN,
+								  PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA *psMMapDataOUT,
+								  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+#if defined (__linux__) || defined (__QNXNTO__)
+	psMMapDataOUT->eError =
+		PVRMMapReleaseMMapData(psPerProc,
+										psMMapDataIN->hMHandle,
+										&psMMapDataOUT->bMUnmap,
+										&psMMapDataOUT->uiRealByteSize,
+										&psMMapDataOUT->uiUserVAddr);
+#else
+
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+	psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVChangeDeviceMemoryAttributesBW(IMG_UINT32 ui32BridgeID,
+                                     PVRSRV_BRIDGE_IN_CHG_DEV_MEM_ATTRIBS *psChgMemAttribIN,
+                                     PVRSRV_BRIDGE_RETURN *psRetOUT,
+                                     PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+	PVR_UNREFERENCED_PARAMETER(psChgMemAttribIN);
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	return 0;
+}
+
+#ifdef PDUMP
+static IMG_INT
+PDumpIsCaptureFrameBW(IMG_UINT32 ui32BridgeID,
+					  IMG_VOID *psBridgeIn,
+					  PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *psPDumpIsCapturingOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+	psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+static IMG_INT
+PDumpCommentBW(IMG_UINT32 ui32BridgeID,
+			   PVRSRV_BRIDGE_IN_PDUMP_COMMENT *psPDumpCommentIN,
+			   PVRSRV_BRIDGE_RETURN *psRetOUT,
+			   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+									  psPDumpCommentIN->ui32Flags);
+	return 0;
+}
+
+static IMG_INT
+PDumpSetFrameBW(IMG_UINT32 ui32BridgeID,
+				PVRSRV_BRIDGE_IN_PDUMP_SETFRAME *psPDumpSetFrameIN,
+				PVRSRV_BRIDGE_RETURN *psRetOUT,
+				PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpRegWithFlagsBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_PDUMP_DUMPREG *psPDumpRegDumpIN,
+					PVRSRV_BRIDGE_RETURN *psRetOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psDeviceNode,
+						   psPDumpRegDumpIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PDumpRegWithFlagsKM (psPDumpRegDumpIN->szRegRegion,
+											psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+											psPDumpRegDumpIN->sHWReg.ui32RegVal,
+											psPDumpRegDumpIN->ui32Flags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpRegPolBW(IMG_UINT32 ui32BridgeID,
+			  PVRSRV_BRIDGE_IN_PDUMP_REGPOL *psPDumpRegPolIN,
+			  PVRSRV_BRIDGE_RETURN *psRetOUT,
+			  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psDeviceNode,
+						   psPDumpRegPolIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psRetOUT->eError =
+		PDumpRegPolWithFlagsKM(psPDumpRegPolIN->szRegRegion,
+							   psPDumpRegPolIN->sHWReg.ui32RegAddr,
+							   psPDumpRegPolIN->sHWReg.ui32RegVal,
+							   psPDumpRegPolIN->ui32Mask,
+							   psPDumpRegPolIN->ui32Flags,
+							   PDUMP_POLL_OPERATOR_EQUAL);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpMemPolBW(IMG_UINT32 ui32BridgeID,
+			  PVRSRV_BRIDGE_IN_PDUMP_MEMPOL *psPDumpMemPolIN,
+			  PVRSRV_BRIDGE_RETURN *psRetOUT,
+			  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPOL);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvMemInfo,
+						   psPDumpMemPolIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpMemPolKM(((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo),
+					  psPDumpMemPolIN->ui32Offset,
+					  psPDumpMemPolIN->ui32Value,
+					  psPDumpMemPolIN->ui32Mask,
+					  psPDumpMemPolIN->eOperator,
+					  psPDumpMemPolIN->ui32Flags,
+					  MAKEUNIQUETAG(pvMemInfo));
+
+	return 0;
+}
+
+static IMG_INT
+PDumpMemBW(IMG_UINT32 ui32BridgeID,
+		   PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM *psPDumpMemDumpIN,
+		   PVRSRV_BRIDGE_RETURN *psRetOUT,
+		   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPMEM);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvMemInfo,
+						   psPDumpMemDumpIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpMemUM(psPerProc,
+				   psPDumpMemDumpIN->hAltLinAddr,
+				   psPDumpMemDumpIN->hLinAddr,
+				   pvMemInfo,
+				   psPDumpMemDumpIN->ui32Offset,
+				   psPDumpMemDumpIN->ui32Bytes,
+				   psPDumpMemDumpIN->ui32Flags,
+				   MAKEUNIQUETAG(pvMemInfo));
+
+	return 0;
+}
+
+static IMG_INT
+PDumpBitmapBW(IMG_UINT32 ui32BridgeID,
+			  PVRSRV_BRIDGE_IN_PDUMP_BITMAP *psPDumpBitmapIN,
+			  PVRSRV_BRIDGE_RETURN *psRetOUT,
+			  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_HANDLE hDevMemContextInt;
+
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+						   psPDumpBitmapIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(	psPerProc->psHandleBase,
+							&hDevMemContextInt,
+							psPDumpBitmapIN->hDevMemContext,
+							PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpBitmapKM(psDeviceNode,
+					  &psPDumpBitmapIN->szFileName[0],
+					  psPDumpBitmapIN->ui32FileOffset,
+					  psPDumpBitmapIN->ui32Width,
+					  psPDumpBitmapIN->ui32Height,
+					  psPDumpBitmapIN->ui32StrideInBytes,
+					  psPDumpBitmapIN->sDevBaseAddr,
+					  hDevMemContextInt,
+					  psPDumpBitmapIN->ui32Size,
+					  psPDumpBitmapIN->ePixelFormat,
+					  psPDumpBitmapIN->eMemFormat,
+					  psPDumpBitmapIN->ui32Flags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpReadRegBW(IMG_UINT32 ui32BridgeID,
+			   PVRSRV_BRIDGE_IN_PDUMP_READREG *psPDumpReadRegIN,
+			   PVRSRV_BRIDGE_RETURN *psRetOUT,
+			   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+						   psPDumpReadRegIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	psRetOUT->eError =
+		PDumpReadRegKM(&psPDumpReadRegIN->szRegRegion[0],
+					   &psPDumpReadRegIN->szFileName[0],
+					   psPDumpReadRegIN->ui32FileOffset,
+					   psPDumpReadRegIN->ui32Address,
+					   psPDumpReadRegIN->ui32Size,
+					   psPDumpReadRegIN->ui32Flags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpMemPagesBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES *psPDumpMemPagesIN,
+				  PVRSRV_BRIDGE_RETURN *psRetOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPAGES);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psDeviceNode,
+						   psPDumpMemPagesIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	return 0;
+}
+
+static IMG_INT
+PDumpDriverInfoBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO *psPDumpDriverInfoIN,
+				  PVRSRV_BRIDGE_RETURN *psRetOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32PDumpFlags;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	ui32PDumpFlags = 0;
+	if(psPDumpDriverInfoIN->bContinuous)
+	{
+		ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+	}
+	psRetOUT->eError =
+		PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+						  ui32PDumpFlags);
+
+	return 0;
+}
+
+static IMG_INT
+PDumpSyncDumpBW(IMG_UINT32 ui32BridgeID,
+				PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC *psPDumpSyncDumpIN,
+				PVRSRV_BRIDGE_RETURN *psRetOUT,
+				PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32Bytes = psPDumpSyncDumpIN->ui32Bytes;
+	IMG_VOID *pvSyncInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPSYNC);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+						   psPDumpSyncDumpIN->hKernelSyncInfo,
+						   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpMemUM(psPerProc,
+				   psPDumpSyncDumpIN->hAltLinAddr,
+				   IMG_NULL,
+				   ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+				   psPDumpSyncDumpIN->ui32Offset,
+				   ui32Bytes,
+				   0,
+				   MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+	return 0;
+}
+
+static IMG_INT
+PDumpSyncPolBW(IMG_UINT32 ui32BridgeID,
+			   PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL *psPDumpSyncPolIN,
+			   PVRSRV_BRIDGE_RETURN *psRetOUT,
+			   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32Offset;
+	IMG_VOID *pvSyncInfo;
+	IMG_UINT32 ui32Value;
+	IMG_UINT32 ui32Mask;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SYNCPOL);
+
+	psRetOUT->eError =
+        PVRSRVLookupHandle(psPerProc->psHandleBase,
+                           &pvSyncInfo,
+						   psPDumpSyncPolIN->hKernelSyncInfo,
+						   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(psPDumpSyncPolIN->bIsRead)
+	{
+		ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+	}
+	else
+	{
+		ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+	}
+
+	/* FIXME:  Move this code to somewhere outside of the bridge */
+	if (psPDumpSyncPolIN->bUseLastOpDumpVal)
+	{
+		if(psPDumpSyncPolIN->bIsRead)
+		{
+			ui32Value = ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncData->ui32LastReadOpDumpVal;
+		}
+		else
+		{
+			ui32Value = ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncData->ui32LastOpDumpVal;
+		}
+		ui32Mask = 0xffffffff;
+	}
+	else
+	{
+		ui32Value = psPDumpSyncPolIN->ui32Value;
+		ui32Mask =  psPDumpSyncPolIN->ui32Mask;
+	}
+
+	psRetOUT->eError =
+		PDumpMemPolKM(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+					  ui32Offset,
+					  ui32Value,
+					  ui32Mask,
+					  PDUMP_POLL_OPERATOR_EQUAL,
+					  0,
+					  MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+	return 0;
+}
+
+
+static IMG_INT
+PDumpCycleCountRegReadBW(IMG_UINT32 ui32BridgeID,
+						 PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *psPDumpCycleCountRegReadIN,
+						 PVRSRV_BRIDGE_RETURN *psRetOUT,
+						 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psDeviceNode,
+						   psPDumpCycleCountRegReadIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PDumpCycleCountRegRead(&psDeviceNode->sDevId,
+						   psPDumpCycleCountRegReadIN->ui32RegOffset,
+						   psPDumpCycleCountRegReadIN->bLastFrame);
+
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+static IMG_INT
+PDumpPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR *psPDumpPDDevPAddrIN,
+				  PVRSRV_BRIDGE_RETURN *psRetOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvMemInfo,
+						   psPDumpPDDevPAddrIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PDumpPDDevPAddrKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo,
+						  psPDumpPDDevPAddrIN->ui32Offset,
+						  psPDumpPDDevPAddrIN->sPDDevPAddr,
+						  MAKEUNIQUETAG(pvMemInfo),
+						  PDUMP_PD_UNIQUETAG);
+	return 0;
+}
+
+static IMG_INT
+PDumpStartInitPhaseBW(IMG_UINT32 ui32BridgeID,
+					  IMG_VOID *psBridgeIn,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpStartInitPhaseKM();
+
+	return 0;
+}
+
+static IMG_INT
+PDumpStopInitPhaseBW(IMG_UINT32 ui32BridgeID,
+					  IMG_VOID *psBridgeIn,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	psRetOUT->eError = PDumpStopInitPhaseKM();
+
+	return 0;
+}
+
+#endif /* PDUMP */
+
+
+static IMG_INT
+PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_GET_MISC_INFO *psGetMiscInfoIN,
+					PVRSRV_BRIDGE_OUT_GET_MISC_INFO *psGetMiscInfoOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+	OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
+			  &psGetMiscInfoIN->sMiscInfo,
+			  sizeof(PVRSRV_MISC_INFO));
+
+	if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) &&
+	    ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) &&
+	    ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+	{
+		/* Client must choose which of memstats and DDK version will be written to
+		 * kernel side buffer */
+		psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) ||
+	    ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) ||
+	    ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+	{
+		/* Alloc kernel side buffer to write into */
+		ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+				    OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+		                    psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+		                    (IMG_VOID **)&psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0,
+							"Output string buffer"));
+
+		psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+		/* Copy result to user */
+		eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+		                           psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+		                           psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
+		                           psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
+
+		/* Free kernel side buffer again */
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+		          psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+		         (IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
+
+		/* Replace output buffer pointer with input pointer, as both are expected
+		 * to point to the same userspace memory.
+		 */
+		psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+		if(eError != PVRSRV_OK)
+		{
+			/* Do error check at the end as we always have to free and reset the
+			 * pointer.
+			 */
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
+			return -EFAULT;
+		}
+	}
+	else
+	{
+		psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+	}
+
+	/* Return on error so exit status of PVRSRVGetMiscInfoKM is propagated to client.
+	 * Don't alloc handles for event object or timer; if error exit status is returned
+	 * the handles should not be used (even if not null) */
+	if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/*
+	 * The handles are not allocated in batch mode as they are shared
+	 * (a shared handle is allocated at most once), and there is no
+	 * resource allocation to undo if the handle allocation fails.
+	 */
+	if (psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+	{
+		psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+													&psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+													psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+													PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+													PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+		if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+
+	}
+
+	if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
+	{
+		/* Allocate handle for SOC OSMemHandle */
+		psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+						  &psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+						  psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+						  PVRSRV_HANDLE_TYPE_SOC_TIMER,
+						  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+		if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
+				PVRSRV_BRIDGE_IN_CONNECT_SERVICES *psConnectServicesIN,
+				PVRSRV_BRIDGE_OUT_CONNECT_SERVICES *psConnectServicesOUT,
+				PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+#if defined(PDUMP)
+	/* Store the per process connection info.
+	 * The Xserver initially connects via PVR2D which sets the persistent flag.
+	 * But, later the Xserver may connect via SGL which doesn't carry the flag (in
+	 * general SGL clients aren't persistent). So we OR in the flag so if it was set
+	 * before it remains set.
+	 */
+	if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PERSIST) != 0)
+	{
+    	psPerProc->bPDumpPersistent = IMG_TRUE;
+	}
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	/* Select whether this client is our 'active' target for pdumping in a
+	 * multi-process environment.
+	 * NOTE: only 1 active target is supported at present.
+	 */
+	if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PDUMP_ACTIVE) != 0)
+	{
+    	psPerProc->bPDumpActive = IMG_TRUE;
+	}
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+#else
+	PVR_UNREFERENCED_PARAMETER(psConnectServicesIN);
+#endif
+	psConnectServicesOUT->ui8KernelArch = (sizeof(void *) == 8) ? 64 : 32;
+	psConnectServicesOUT->hKernelServices = (IMG_UINT64)(uintptr_t)(void *) psPerProc->hPerProcData;
+	psConnectServicesOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
+				   IMG_VOID *psBridgeIn,
+				   PVRSRV_BRIDGE_RETURN *psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+	/* just return OK, per-process data is cleaned up by resmgr */
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+static IMG_INT
+PVRSRVEnumerateDCBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+					PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
+
+	psEnumDispClassOUT->eError =
+		PVRSRVEnumerateDCKM(psEnumDispClassIN->eDeviceClass,
+							&psEnumDispClassOUT->ui32NumDevices,
+							&psEnumDispClassOUT->ui32DevID[0]);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVOpenDCDeviceBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceIN,
+					 PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc, 1)
+
+	psOpenDispClassDeviceOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psOpenDispClassDeviceIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psOpenDispClassDeviceOUT->eError =
+		PVRSRVOpenDCDeviceKM(psPerProc,
+							 psOpenDispClassDeviceIN->ui32DeviceID,
+							 hDevCookieInt,
+							 &hDispClassInfoInt);
+
+	if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psOpenDispClassDeviceOUT->hDeviceKM,
+					  hDispClassInfoInt,
+					  PVRSRV_HANDLE_TYPE_DISP_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+	COMMIT_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc)
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVCloseDCDeviceBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *psCloseDispClassDeviceIN,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psCloseDispClassDeviceIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psCloseDispClassDeviceIN->hDeviceKM,
+							PVRSRV_HANDLE_TYPE_DISP_INFO);
+	return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCFormatsBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsIN,
+					  PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS);
+
+	psEnumDispClassFormatsOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psEnumDispClassFormatsIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psEnumDispClassFormatsOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psEnumDispClassFormatsOUT->eError =
+		PVRSRVEnumDCFormatsKM(pvDispClassInfoInt,
+							  &psEnumDispClassFormatsOUT->ui32Count,
+							  psEnumDispClassFormatsOUT->asFormat);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCDimsBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsIN,
+				   PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS);
+
+	psEnumDispClassDimsOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psEnumDispClassDimsIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+	if(psEnumDispClassDimsOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psEnumDispClassDimsOUT->eError =
+		PVRSRVEnumDCDimsKM(pvDispClassInfoInt,
+						   &psEnumDispClassDimsIN->sFormat,
+						   &psEnumDispClassDimsOUT->ui32Count,
+						   psEnumDispClassDimsOUT->asDim);
+
+	return 0;
+}
+
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
+static IMG_INT
+PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,  //IMG_HANDLE *phGetDispClassSysBufferIN,
+						  PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hBufferInt;
+	IMG_VOID *pvDispClassInfoInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc, 1)
+
+	psGetDispClassSysBufferOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfoInt,
+						   psGetDispClassSysBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDispClassSysBufferOUT->eError =
+		PVRSRVGetDCSystemBufferKM(pvDispClassInfoInt,
+								  &hBufferInt);
+
+	if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* PRQA S 1461 6 */ /* ignore warning about enum type being converted */
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+						 &psGetDispClassSysBufferOUT->hBuffer,
+						 hBufferInt,
+						 PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+						 (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+						 psGetDispClassSysBufferIN->hDeviceKM);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc)
+
+	return 0;
+}
+#endif
+
+static IMG_INT
+PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO *psGetDispClassInfoIN,
+				  PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO *psGetDispClassInfoOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_INFO);
+
+	psGetDispClassInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psGetDispClassInfoIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psGetDispClassInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDispClassInfoOUT->eError =
+		PVRSRVGetDCInfoKM(pvDispClassInfo,
+						  &psGetDispClassInfoOUT->sDisplayInfo);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainIN,
+						  PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_HANDLE hSwapChainInt;
+	IMG_UINT32	ui32SwapChainID;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc, 1)
+
+	psCreateDispClassSwapChainOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psCreateDispClassSwapChainIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+	if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* Get ui32SwapChainID from input */
+	ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
+
+	psCreateDispClassSwapChainOUT->eError =
+		PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+								  psCreateDispClassSwapChainIN->ui32Flags,
+								  &psCreateDispClassSwapChainIN->sDstSurfAttrib,
+								  &psCreateDispClassSwapChainIN->sSrcSurfAttrib,
+								  psCreateDispClassSwapChainIN->ui32BufferCount,
+								  psCreateDispClassSwapChainIN->ui32OEMFlags,
+								  &hSwapChainInt,
+								  &ui32SwapChainID
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+								 ,psCreateDispClassSwapChainIN->i32TimelineFd
+#endif
+								);
+
+	if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* Pass ui32SwapChainID to output */
+	psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psCreateDispClassSwapChainOUT->hSwapChain,
+					  hSwapChainInt,
+					  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+					  psCreateDispClassSwapChainIN->hDeviceKM);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc)
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+						   PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN *psDestroyDispClassSwapChainIN,
+						   PVRSRV_BRIDGE_RETURN *psRetOUT,
+						   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSwapChain,
+						   psDestroyDispClassSwapChainIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVDestroyDCSwapChainKM(pvSwapChain);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psDestroyDispClassSwapChainIN->hSwapChain,
+							PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstRectBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassDstRectIN,
+					 PVRSRV_BRIDGE_RETURN *psRetOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassDstRectIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassDstRectIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCDstRectKM(pvDispClassInfo,
+							 pvSwapChain,
+							 &psSetDispClassDstRectIN->sRect);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcRectBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassSrcRectIN,
+					 PVRSRV_BRIDGE_RETURN *psRetOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassSrcRectIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassSrcRectIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCSrcRectKM(pvDispClassInfo,
+							 pvSwapChain,
+							 &psSetDispClassSrcRectIN->sRect);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstColourKeyBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassColKeyIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassColKeyIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCDstColourKeyKM(pvDispClassInfo,
+								  pvSwapChain,
+								  psSetDispClassColKeyIN->ui32CKColour);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcColourKeyBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSetDispClassColKeyIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSetDispClassColKeyIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVSetDCSrcColourKeyKM(pvDispClassInfo,
+								  pvSwapChain,
+								  psSetDispClassColKeyIN->ui32CKColour);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersIN,
+					 PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc, PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+
+	psGetDispClassBuffersOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psGetDispClassBuffersIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetDispClassBuffersOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psGetDispClassBuffersIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+	if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psGetDispClassBuffersOUT->eError =
+		PVRSRVGetDCBuffersKM(pvDispClassInfo,
+							 pvSwapChain,
+							 &psGetDispClassBuffersOUT->ui32BufferCount,
+							 psGetDispClassBuffersOUT->ahBuffer,
+							 psGetDispClassBuffersOUT->asPhyAddr);
+	if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVR_ASSERT(psGetDispClassBuffersOUT->ui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+	for(i = 0; i < psGetDispClassBuffersOUT->ui32BufferCount; i++)
+	{
+		IMG_HANDLE hBufferExt;
+
+	/* PRQA S 1461 15 */ /* ignore warning about enum type being converted */
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							 &hBufferExt,
+							 psGetDispClassBuffersOUT->ahBuffer[i],
+							 PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+							 (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+							 psGetDispClassBuffersIN->hSwapChain);
+
+		psGetDispClassBuffersOUT->ahBuffer[i] = hBufferExt;
+	}
+
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc)
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *psSwapDispClassBufferIN,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChainBuf;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSwapDispClassBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+						   &pvSwapChainBuf,
+						   psSwapDispClassBufferIN->hBuffer,
+						   PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+						   psSwapDispClassBufferIN->hDeviceKM);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psRetOUT->eError =
+		PVRSRVSwapToDCBufferKM(pvDispClassInfo,
+							   pvSwapChainBuf,
+							   psSwapDispClassBufferIN->ui32SwapInterval,
+							   psSwapDispClassBufferIN->hPrivateTag,
+							   psSwapDispClassBufferIN->ui32ClipRectCount,
+							   psSwapDispClassBufferIN->sClipRect);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBuffer2BW(IMG_UINT32 ui32BridgeID,
+						PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2 *psSwapDispClassBufferIN,
+						PVRSRV_BRIDGE_OUT_SWAP_DISPCLASS_TO_BUFFER2 *psSwapDispClassBufferOUT,
+						PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvPrivData = IMG_NULL;
+	IMG_HANDLE hFence = IMG_NULL;
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+	IMG_HANDLE      *phKernelMemInfos;
+	IMG_HANDLE	*phKernelSyncInfos;
+	IMG_UINT32 i;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	int iReleaseFd;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0))
+	iReleaseFd = get_unused_fd_flags(0);
+#else
+	iReleaseFd = get_unused_fd();
+#endif
+
+	if(iReleaseFd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+								__func__, iReleaseFd));
+		return 0;
+	}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2);
+
+	psSwapDispClassBufferOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSwapDispClassBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psSwapDispClassBufferOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_INFO handle"));
+		return 0;
+	}
+
+	psSwapDispClassBufferOUT->eError =
+		PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+							  &pvSwapChain,
+							  psSwapDispClassBufferIN->hSwapChain,
+							  PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+							  psSwapDispClassBufferIN->hDeviceKM);
+	if(psSwapDispClassBufferOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_BUFFER handle"));
+		return 0;
+	}
+
+	if(!OSAccessOK(PVR_VERIFY_WRITE,
+				   psSwapDispClassBufferIN->hKernelMemInfos,
+				   sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelMemInfos"));
+		return -EFAULT;
+	}
+
+	if(!OSAccessOK(PVR_VERIFY_WRITE,
+				   psSwapDispClassBufferIN->hKernelSyncInfos,
+				   sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelSyncInfos"));
+		return -EFAULT;
+	}
+
+	phKernelMemInfos = (IMG_HANDLE *)psSwapDispClassBufferIN->hKernelMemInfos;
+	phKernelSyncInfos = (IMG_HANDLE *)psSwapDispClassBufferIN->hKernelSyncInfos;
+	for (i = 0; i < psSwapDispClassBufferIN->ui32NumMemInfos; i++)
+	{
+		PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+		psSwapDispClassBufferOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   (IMG_PVOID *)&psKernelMemInfo,
+							   phKernelMemInfos[i],
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+		if(psSwapDispClassBufferOUT->eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up MEM_INFO handle"));
+			return 0;
+		}
+		phKernelMemInfos[i] = psKernelMemInfo;
+
+#if !(defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE))
+		{
+			PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+			psSwapDispClassBufferOUT->eError =
+				PVRSRVLookupHandle(psPerProc->psHandleBase,
+								   (IMG_PVOID *)&psKernelSyncInfo,
+								   phKernelSyncInfos[i],
+								   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+			if(psSwapDispClassBufferOUT->eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up SYNC_INFO handle"));
+				return 0;
+			}
+			phKernelSyncInfos[i] = psKernelSyncInfo;
+		}
+#endif /* !defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+	}
+
+	if(psSwapDispClassBufferIN->ui32PrivDataLength > 0)
+	{
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+					  psSwapDispClassBufferIN->ui32PrivDataLength,
+					  (IMG_VOID **)&pvPrivData, IMG_NULL,
+					  "Swap Command Private Data") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2BW: Failed to allocate private data space"));
+			return -ENOMEM;
+		}
+
+		if(CopyFromUserWrapper(psPerProc,
+							   ui32BridgeID,
+							   pvPrivData,
+							   psSwapDispClassBufferIN->hPrivData,
+							   psSwapDispClassBufferIN->ui32PrivDataLength) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to copy private data"));
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+					  psSwapDispClassBufferIN->ui32PrivDataLength,
+					  pvPrivData, IMG_NULL);
+	        return -EFAULT;
+		}
+	}
+
+	psSwapDispClassBufferOUT->eError =
+		PVRSRVSwapToDCBuffer2KM(pvDispClassInfo,
+								pvSwapChain,
+								psSwapDispClassBufferIN->ui32SwapInterval,
+								(PVRSRV_KERNEL_MEM_INFO**) psSwapDispClassBufferIN->hKernelMemInfos,
+								(PVRSRV_KERNEL_SYNC_INFO**) psSwapDispClassBufferIN->hKernelSyncInfos,
+								psSwapDispClassBufferIN->ui32NumMemInfos,
+								pvPrivData,
+								psSwapDispClassBufferIN->ui32PrivDataLength,
+								&hFence);
+
+	if(psSwapDispClassBufferOUT->eError != PVRSRV_OK)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  psSwapDispClassBufferIN->ui32PrivDataLength,
+				  pvPrivData, IMG_NULL);
+	}
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	if(hFence)
+	{
+		struct sync_fence *psFence = hFence;
+		sync_fence_install(psFence, iReleaseFd);
+	psSwapDispClassBufferOUT->hFence = (IMG_HANDLE)(uintptr_t)iReleaseFd;
+	}
+	else
+	{
+		psSwapDispClassBufferOUT->hFence = (IMG_HANDLE)-1;
+		put_unused_fd(iReleaseFd);
+	}
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	if(hFence)
+	{
+		struct sync_file *psSyncFile = sync_file_create(hFence);
+		fd_install(iReleaseFd, psSyncFile->file);
+		psSwapDispClassBufferOUT->hFence = (IMG_HANDLE)(uintptr_t)iReleaseFd;
+	}
+	else
+	{
+		psSwapDispClassBufferOUT->hFence = (IMG_HANDLE)-1;
+		put_unused_fd(iReleaseFd);
+	}
+#else /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+	psSwapDispClassBufferOUT->hFence = (IMG_HANDLE)-1;
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+    return 0;
+}
+
+
+
+static IMG_INT
+PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvDispClassInfo;
+	IMG_VOID *pvSwapChain;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvDispClassInfo,
+						   psSwapDispClassSystemIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_DISP_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+						   &pvSwapChain,
+						   psSwapDispClassSystemIN->hSwapChain,
+						   PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+						   psSwapDispClassSystemIN->hDeviceKM);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+	psRetOUT->eError =
+		PVRSRVSwapToDCSystemKM(pvDispClassInfo,
+							   pvSwapChain);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVOpenBCDeviceBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceIN,
+					 PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hBufClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc, 1)
+
+	psOpenBufferClassDeviceOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psOpenBufferClassDeviceIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psOpenBufferClassDeviceOUT->eError =
+		PVRSRVOpenBCDeviceKM(psPerProc,
+							 psOpenBufferClassDeviceIN->ui32DeviceID,
+							 hDevCookieInt,
+							 &hBufClassInfo);
+	if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psOpenBufferClassDeviceOUT->hDeviceKM,
+					  hBufClassInfo,
+					  PVRSRV_HANDLE_TYPE_BUF_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc)
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVCloseBCDeviceBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *psCloseBufferClassDeviceIN,
+					  PVRSRV_BRIDGE_RETURN *psRetOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvBufClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvBufClassInfo,
+						   psCloseBufferClassDeviceIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_BUF_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVCloseBCDeviceKM(pvBufClassInfo);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+										   psCloseBufferClassDeviceIN->hDeviceKM,
+										   PVRSRV_HANDLE_TYPE_BUF_INFO);
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCInfoBW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *psGetBufferClassInfoIN,
+				  PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *psGetBufferClassInfoOUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvBufClassInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO);
+
+	psGetBufferClassInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvBufClassInfo,
+						   psGetBufferClassInfoIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_BUF_INFO);
+	if(psGetBufferClassInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetBufferClassInfoOUT->eError =
+		PVRSRVGetBCInfoKM(pvBufClassInfo,
+						  &psGetBufferClassInfoOUT->sBufferInfo);
+	return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCBufferBW(IMG_UINT32 ui32BridgeID,
+					PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+					PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+					PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_VOID *pvBufClassInfo;
+	IMG_HANDLE hBufferInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1)
+
+	psGetBufferClassBufferOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvBufClassInfo,
+						   psGetBufferClassBufferIN->hDeviceKM,
+						   PVRSRV_HANDLE_TYPE_BUF_INFO);
+	if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetBufferClassBufferOUT->eError =
+		PVRSRVGetBCBufferKM(pvBufClassInfo,
+							psGetBufferClassBufferIN->ui32BufferIndex,
+							&hBufferInt);
+
+	if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* PRQA S 1461 6 */ /* ignore warning about enum type being converted */
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+						 &psGetBufferClassBufferOUT->hBuffer,
+						 hBufferInt,
+						 PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+						 (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE |  PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+						 psGetBufferClassBufferIN->hDeviceKM);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc)
+
+	return 0;
+}
+
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+static IMG_INT
+PVRSRVAllocSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemIN,
+							 PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc, 1)
+
+	psAllocSharedSysMemOUT->eError =
+		PVRSRVAllocSharedSysMemoryKM(psPerProc,
+									 psAllocSharedSysMemIN->ui32Flags,
+									 psAllocSharedSysMemIN->uSize,
+									 &psKernelMemInfo);
+	if(psAllocSharedSysMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	OSMemSet(&psAllocSharedSysMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+	psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+			psKernelMemInfo->pvLinAddrKM;
+
+	psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psAllocSharedSysMemOUT->sClientMemInfo.ui32Flags =
+		psKernelMemInfo->ui32Flags;
+    psAllocSharedSysMemOUT->sClientMemInfo.uAllocSize =
+        psKernelMemInfo->uAllocSize;
+	psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psAllocSharedSysMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc)
+
+	return 0;
+}
+
+static IMG_INT
+PVRSRVFreeSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+							PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *psFreeSharedSysMemIN,
+							PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *psFreeSharedSysMemOUT,
+							PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM);
+
+	psFreeSharedSysMemOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psKernelMemInfo,
+						   psFreeSharedSysMemIN->hKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+
+	if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+		return 0;
+
+	psFreeSharedSysMemOUT->eError =
+		PVRSRVFreeSharedSysMemoryKM(psKernelMemInfo);
+	if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+		return 0;
+
+	psFreeSharedSysMemOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psFreeSharedSysMemIN->hKernelMemInfo,
+							PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	return 0;
+}
+
+static IMG_INT
+PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM *psMapMemInfoMemIN,
+					  PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM *psMapMemInfoMemOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+	PVRSRV_HANDLE_TYPE eHandleType;
+	IMG_HANDLE	hParent;
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_MEMINFO_MEM);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc, 2)
+
+	psMapMemInfoMemOUT->eError =
+		PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+						   (IMG_VOID **)&psKernelMemInfo,
+						   &eHandleType,
+						   psMapMemInfoMemIN->hKernelMemInfo);
+	if(psMapMemInfoMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	switch (eHandleType)
+	{
+#if defined(PVR_SECURE_HANDLES)
+		case PVRSRV_HANDLE_TYPE_MEM_INFO:
+		case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+		case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+#else
+		case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+			break;
+		default:
+			psMapMemInfoMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+			return 0;
+	}
+
+	/*
+	 * To prevent the building up of deep chains of subhandles, parent
+	 * the new meminfo off the parent of the input meminfo, if it has
+	 * a parent.
+	 */
+	psMapMemInfoMemOUT->eError =
+		PVRSRVGetParentHandle(psPerProc->psHandleBase,
+					&hParent,
+					psMapMemInfoMemIN->hKernelMemInfo,
+					eHandleType);
+	if (psMapMemInfoMemOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+	if (hParent == IMG_NULL)
+	{
+		hParent = psMapMemInfoMemIN->hKernelMemInfo;
+	}
+
+	OSMemSet(&psMapMemInfoMemOUT->sClientMemInfo,
+			 0,
+			 sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+	psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+			psKernelMemInfo->pvLinAddrKM;
+
+	psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = 0;
+	psMapMemInfoMemOUT->sClientMemInfo.sDevVAddr =
+		psKernelMemInfo->sDevVAddr;
+	psMapMemInfoMemOUT->sClientMemInfo.ui32Flags =
+		psKernelMemInfo->ui32Flags;
+    psMapMemInfoMemOUT->sClientMemInfo.uAllocSize =
+        psKernelMemInfo->uAllocSize;
+	psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo,
+					  psKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  hParent);
+
+	if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+		/* signal no syncinfo */
+		OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
+				 0,
+				 sizeof (PVRSRV_CLIENT_SYNC_INFO));
+	}
+	else
+	{
+		/* and setup the sync info */
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+		psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
+			psKernelMemInfo->psKernelSyncInfo->psSyncData;
+		psMapMemInfoMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+		psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+		psMapMemInfoMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+			psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+		psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo =
+			psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+
+		psMapMemInfoMemOUT->sClientMemInfo.psClientSyncInfo = &psMapMemInfoMemOUT->sClientSyncInfo;
+
+		PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							 &psMapMemInfoMemOUT->sClientSyncInfo.hKernelSyncInfo,
+							 psKernelMemInfo->psKernelSyncInfo,
+							 PVRSRV_HANDLE_TYPE_SYNC_INFO,
+							 PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+							 psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo);
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc)
+
+	return 0;
+}
+
+
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+		IMG_VOID *psBridgeIn,
+		IMG_VOID *psBridgeOut,
+		PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if !defined(DEBUG)
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+	PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+#if defined(DEBUG_BRIDGE_KM)
+	PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u (%s) mapped to "
+			 "Dummy Wrapper (probably not what you want!)",
+			 __FUNCTION__, ui32BridgeID, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+	PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u mapped to "
+			 "Dummy Wrapper (probably not what you want!)",
+			 __FUNCTION__, ui32BridgeID));
+#endif
+	return -ENOTTY;
+}
+
+
+/*!
+ * *****************************************************************************
+ * @brief A wrapper for filling in the g_BridgeDispatchTable array that does
+ * 		  error checking.
+ *
+ * @param ui32Index
+ * @param pszIOCName
+ * @param pfFunction
+ * @param pszFunctionName
+ *
+ * @return
+ ********************************************************************************/
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+					   const IMG_CHAR *pszIOCName,
+					   BridgeWrapperFunction pfFunction,
+					   const IMG_CHAR *pszFunctionName)
+{
+	static IMG_UINT uiPrevIndex = ~0U;		/* -1 */
+#if !defined(DEBUG)
+	PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+	PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+	/* INTEGRATION_POINT: Enable this to dump out the dispatch table entries */
+	PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
+#endif
+
+	/* We should never be over-writing a previous entry.
+	 * If we are, tell the world about it.
+	 * NOTE: This shouldn't be debug only since switching from debug->release
+	 * etc is likly to modify the available ioctls and thus be a point where
+	 * mistakes are exposed. This isn't run at at a performance critical time.
+	 */
+	if(g_BridgeDispatchTable[ui32Index].pfFunction)
+	{
+#if defined(DEBUG_BRIDGE_KM)
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+				 __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+		PVR_DPF((PVR_DBG_ERROR,
+				 "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%u)",
+				 __FUNCTION__, pszIOCName, ui32Index));
+#endif
+		PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+	}
+
+	/* Any gaps are sub-optimal in-terms of memory usage, but we are mainly
+	 * interested in spotting any large gap of wasted memory that could be
+	 * accidentally introduced.
+	 *
+	 * This will currently flag up any gaps > 5 entries.
+	 *
+	 * NOTE: This shouldn't be debug only since switching from debug->release
+	 * etc is likly to modify the available ioctls and thus be a point where
+	 * mistakes are exposed. This isn't run at at a performance critical time.
+	 */
+//	if((uiPrevIndex != (IMG_UINT)-1) &&
+	if((uiPrevIndex != ~0U) &&
+	   ((ui32Index >= uiPrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+		(ui32Index <= uiPrevIndex)))
+	{
+#if defined(DEBUG_BRIDGE_KM)
+		PVR_DPF((PVR_DBG_WARNING,
+				 "%s: There is a gap in the dispatch table between indices %u (%s) and %u (%s)",
+				 __FUNCTION__, uiPrevIndex, g_BridgeDispatchTable[uiPrevIndex].pszIOCName,
+				 ui32Index, pszIOCName));
+#else
+		PVR_DPF((PVR_DBG_WARNING,
+				 "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+				 __FUNCTION__, (IMG_UINT)uiPrevIndex, (IMG_UINT)ui32Index, pszIOCName));
+#endif
+		PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+	}
+
+	g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+	g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+	g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+	g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+	g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+	uiPrevIndex = ui32Index;
+}
+
+static IMG_INT
+PVRSRVInitSrvConnectBW(IMG_UINT32 ui32BridgeID,
+					   IMG_VOID *psBridgeIn,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	/* PRQA S 3415 1 */ /* side effects needed - if any step fails */
+	if((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+	{
+		psRetOUT->eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
+		return 0;
+	}
+
+#if defined (__linux__) || defined (__QNXNTO__)
+	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+	psPerProc->bInitProcess = IMG_TRUE;
+
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVInitSrvDisconnectBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *psInitSrvDisconnectIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_DISCONNECT);
+
+	if(!psPerProc->bInitProcess)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_SRV_DISCONNECT_FAILED;
+		return 0;
+	}
+
+	psPerProc->bInitProcess = IMG_FALSE;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+    psPerProc->bPDumpActive = IMG_FALSE;
+#endif
+
+	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+	PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+	psRetOUT->eError = PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+	PVRSRVSetInitServerState( PVRSRV_INIT_SERVER_SUCCESSFUL ,
+				((psRetOUT->eError == PVRSRV_OK) && (psInitSrvDisconnectIN->bInitSuccesful))
+				? IMG_TRUE : IMG_FALSE);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectWaitBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *psEventObjectWaitIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hOSEventKM;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_WAIT);
+
+	psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hOSEventKM,
+						   psEventObjectWaitIN->hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = OSEventObjectWaitKM(hOSEventKM);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectOpenBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *psEventObjectOpenIN,
+						  PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *psEventObjectOpenOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_OPEN);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc, 1)
+
+	psEventObjectOpenOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psEventObjectOpenIN->sEventObject.hOSEventKM,
+						   psEventObjectOpenIN->sEventObject.hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+	if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psEventObjectOpenOUT->eError = OSEventObjectOpenKM(&psEventObjectOpenIN->sEventObject, &psEventObjectOpenOUT->hOSEvent);
+
+	if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psEventObjectOpenOUT->hOSEvent,
+					  psEventObjectOpenOUT->hOSEvent,
+					  PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc)
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectCloseBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *psEventObjectCloseIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hOSEventKM;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psEventObjectCloseIN->sEventObject.hOSEventKM,
+						   psEventObjectCloseIN->sEventObject.hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &hOSEventKM,
+						   psEventObjectCloseIN->hOSEventKM,
+						   PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = OSEventObjectCloseKM(&psEventObjectCloseIN->sEventObject, hOSEventKM);
+
+	return 0;
+}
+
+
+typedef struct _MODIFY_SYNC_OP_INFO
+{
+	IMG_HANDLE  hResItem;
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	IMG_UINT32 	ui32ModifyFlags;
+	IMG_UINT32	ui32ReadOpsPendingSnapShot;
+	IMG_UINT32	ui32WriteOpsPendingSnapShot;
+	IMG_UINT32	ui32ReadOps2PendingSnapShot;
+} MODIFY_SYNC_OP_INFO;
+
+
+static PVRSRV_ERROR DoQuerySyncOpsSatisfied(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+											IMG_UINT32 ui32ReadOpsPendingSnapShot,
+											IMG_UINT32 ui32WriteOpsPendingSnapShot,
+											IMG_UINT32 ui32ReadOps2PendingSnapShot)
+{
+	IMG_UINT32 ui32WriteOpsPending;
+	IMG_UINT32 ui32ReadOpsPending;
+	IMG_UINT32 ui32ReadOps2Pending;
+
+	/*
+	 *
+	 * We wait until the complete count reaches _or_moves_past_ the
+	 * snapshot value.
+	 *
+	 */
+
+	if (!psKernelSyncInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/*
+	 let p be the pending ops count
+	 let c be the complete ops count
+	 let p' be the previously taken snapshot
+
+	 if p exceeds c by an amount greater than that by which
+	 p exceeds p', then the condition is not yet satisfied.
+
+	 Note that (p - c) can never be negative, and neither can (p - p')
+	 so we can do the comparison using unsigned arithmetic
+	*/
+	ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+	ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+	ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+	if((ui32WriteOpsPending - ui32WriteOpsPendingSnapShot >=
+		ui32WriteOpsPending - psKernelSyncInfo->psSyncData->ui32WriteOpsComplete) &&
+	   (ui32ReadOpsPending - ui32ReadOpsPendingSnapShot >=
+		ui32ReadOpsPending - psKernelSyncInfo->psSyncData->ui32ReadOpsComplete) &&
+		(ui32ReadOps2Pending - ui32ReadOps2PendingSnapShot >=
+		ui32ReadOps2Pending - psKernelSyncInfo->psSyncData->ui32ReadOps2Complete))
+	{
+#if defined(PDUMP) && !defined(SUPPORT_VGX)
+		/* pdump the sync pol: reads */
+		PDumpComment("Poll for read ops complete to reach value (pdump: %u, actual snapshot: %u)",
+					 psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					 ui32ReadOpsPendingSnapShot);
+		PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+					  offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+					  psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					  0xFFFFFFFF,
+					  PDUMP_POLL_OPERATOR_EQUAL, /*  * see "NB" below */
+					  0,
+					  MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+
+		/* pdump the sync pol: writes */
+		PDumpComment("Poll for write ops complete to reach value (pdump: %u, actual snapshot: %u)",
+					 psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
+					 ui32WriteOpsPendingSnapShot);
+		PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+					  offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+					  psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
+					  0xFFFFFFFF,
+					  PDUMP_POLL_OPERATOR_EQUAL, /*  * see "NB" below */
+					  0,
+					  MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+		/* NB: FIXME -- really need to POL on an expression to
+		   accurately reflect the condition we need to check.  How to
+		   do this in PDUMP? */
+#endif
+		return PVRSRV_OK;
+	}
+	else
+	{
+		return PVRSRV_ERROR_RETRY;
+	}
+}
+
+
+static PVRSRV_ERROR DoModifyCompleteSyncOps(MODIFY_SYNC_OP_INFO *psModSyncOpInfo)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+	psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+	if (!psKernelSyncInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* If user has used the API correctly, we will always have reached the pending snapshot.
+	   We should catch this error on the client side of the bridge and report it in an obvious way */
+	if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+	   || (psModSyncOpInfo->ui32ReadOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+	{
+		return PVRSRV_ERROR_BAD_SYNC_STATE;
+	}
+
+	/* update the WOpComplete */
+	if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+	{
+		psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+	}
+
+	/* update the ROpComplete */
+	if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+	{
+		psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+	}
+
+	/* update the ROp2Complete */
+	if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO2_INC)
+	{
+		psKernelSyncInfo->psSyncData->ui32ReadOps2Complete++;
+	}
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_MODOBJ, PVRSRV_TRACE_CLASS_CMD_COMP_START, MODOBJ_TOKEN_COMPLETE_PENDING);
+	PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_MODOBJ, MODOBJ_TOKEN_SYNC_UPDATE,
+					psKernelSyncInfo, PVRSRV_SYNCOP_COMPLETE);
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_MODOBJ, PVRSRV_TRACE_CLASS_CMD_COMP_END, MODOBJ_TOKEN_COMPLETE_PENDING);
+
+	return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID		pvParam,
+                                                    IMG_UINT32  ui32Param,
+                                                    IMG_BOOL    bDummy)
+{
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	if (!pvParam)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psModSyncOpInfo = (MODIFY_SYNC_OP_INFO*)pvParam;
+
+	if (psModSyncOpInfo->psKernelSyncInfo)
+	{
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			if (DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
+										psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+										psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+										psModSyncOpInfo->ui32ReadOps2PendingSnapShot) == PVRSRV_OK)
+			{
+				goto OpFlushedComplete;
+			}
+			PVR_DPF((PVR_DBG_WARNING, "ModifyCompleteSyncOpsCallBack: waiting for current Ops to flush"));
+            OSSleepms(1);
+		} END_LOOP_UNTIL_TIMEOUT();
+
+		PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: timeout whilst waiting for current Ops to flush."));
+		PVR_DPF((PVR_DBG_ERROR, "  Write ops pending snapshot = %d, write ops complete = %d",
+				 psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+				 psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32WriteOpsComplete));
+		PVR_DPF((PVR_DBG_ERROR, "  Read ops pending snapshot = %d, read ops complete = %d",
+				 psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+				 psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete));
+		PVR_DPF((PVR_DBG_ERROR, "  Read ops pending snapshot = %d, read ops2 complete = %d",
+				 psModSyncOpInfo->ui32ReadOps2PendingSnapShot,
+				 psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOps2Complete));
+		return PVRSRV_ERROR_TIMEOUT;
+
+OpFlushedComplete:
+		DoModifyCompleteSyncOps(psModSyncOpInfo);
+		PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 	sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
+
+	/* re-kick all services managed devices */
+	PVRSRVScheduleDeviceCallbacks();
+
+	return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVCreateSyncInfoModObjBW(IMG_UINT32                                         ui32BridgeID,
+									 IMG_VOID                                           *psBridgeIn,
+									 PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ  *psCreateSyncInfoModObjOUT,
+									 PVRSRV_PER_PROCESS_DATA		   		            *psPerProc)
+{
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+
+	PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc, 1)
+
+	ASSIGN_AND_EXIT_ON_ERROR(psCreateSyncInfoModObjOUT->eError,
+			  OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(MODIFY_SYNC_OP_INFO),
+			  (IMG_VOID **)&psModSyncOpInfo, 0,
+			  "ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
+
+	psModSyncOpInfo->psKernelSyncInfo = IMG_NULL; /* mark it as empty */
+
+	psCreateSyncInfoModObjOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+																  &psCreateSyncInfoModObjOUT->hKernelSyncInfoModObj,
+																  psModSyncOpInfo,
+																  PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ,
+																  PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+	if (psCreateSyncInfoModObjOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psModSyncOpInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+												  RESMAN_TYPE_MODIFY_SYNC_OPS,
+												  psModSyncOpInfo,
+												  0,
+												  &ModifyCompleteSyncOpsCallBack);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc)
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVDestroySyncInfoModObjBW(IMG_UINT32                                          ui32BridgeID,
+							  PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ          *psDestroySyncInfoModObjIN,
+							  PVRSRV_BRIDGE_RETURN                                *psDestroySyncInfoModObjOUT,
+							  PVRSRV_PER_PROCESS_DATA		   		              *psPerProc)
+{
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ);
+
+	psDestroySyncInfoModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+																	(IMG_VOID**)&psModSyncOpInfo,
+																	psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+																	PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+	if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	if(psModSyncOpInfo->psKernelSyncInfo != IMG_NULL)
+	{
+		/* Not empty */
+		psDestroySyncInfoModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	psDestroySyncInfoModObjOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+																	 psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+																	 PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+
+	if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVReleaseHandle failed"));
+		return 0;
+	}
+
+    psDestroySyncInfoModObjOUT->eError = ResManFreeResByPtr(psModSyncOpInfo->hResItem, CLEANUP_WITH_POLL);
+	if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: ResManFreeResByPtr failed"));
+		return 0;
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyPendingSyncOpsBW(IMG_UINT32									ui32BridgeID,
+						      PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS	*psModifySyncOpsIN,
+							  PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS	*psModifySyncOpsOUT,
+							  PVRSRV_PER_PROCESS_DATA					*psPerProc)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS);
+
+	psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+													(IMG_VOID**)&psModSyncOpInfo,
+													psModifySyncOpsIN->hKernelSyncInfoModObj,
+													PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+	if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+													(IMG_VOID**)&psKernelSyncInfo,
+													psModifySyncOpsIN->hKernelSyncInfo,
+													PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	if(psModSyncOpInfo->psKernelSyncInfo)
+	{
+		/* SyncInfoModification is not empty */
+		psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
+		PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo Modification object is not empty"));
+		return 0;
+	}
+
+	/* Should never happen, but check to be sure */
+	if (psKernelSyncInfo == IMG_NULL)
+	{
+		psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo bad handle"));
+		return 0;
+	}
+
+	PVRSRVKernelSyncInfoIncRef(psKernelSyncInfo, IMG_NULL);
+	/* setup info to store in resman */
+	psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
+	psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
+	psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+	psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+	psModSyncOpInfo->ui32ReadOps2PendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+	/* We return PRE-INCREMENTED versions of all sync Op Values */
+
+	psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+	psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+	psModifySyncOpsOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_MODOBJ, PVRSRV_TRACE_CLASS_CMD_START, MODOBJ_TOKEN_MODIFY_PENDING);
+	if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+	{
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_MODOBJ, MODOBJ_TOKEN_WRITE_SYNC,
+						psKernelSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+	}
+	else if (psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+	{
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_MODOBJ, MODOBJ_TOKEN_READ_SYNC,
+						psKernelSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+	}
+	else if (psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO2_INC)
+	{
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_MODOBJ, MODOBJ_TOKEN_READ2_SYNC,
+						psKernelSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+	}
+	else
+	{
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_MODOBJ, MODOBJ_TOKEN_READ_WRITE_SYNC,
+						psKernelSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+	}
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_MODOBJ, PVRSRV_TRACE_CLASS_CMD_END, MODOBJ_TOKEN_MODIFY_PENDING);
+
+	if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+	{
+		SyncTakeWriteOp(psKernelSyncInfo, SYNC_OP_CLASS_MODOBJ);
+	}
+
+	if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+	{
+		SyncTakeReadOp(psKernelSyncInfo, SYNC_OP_CLASS_MODOBJ);
+	}
+
+	if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO2_INC)
+	{
+		SyncTakeReadOp2(psKernelSyncInfo, SYNC_OP_CLASS_MODOBJ);
+	}
+
+	/* pull the resman item to the front of the list */
+	psModifySyncOpsOUT->eError = ResManDissociateRes(psModSyncOpInfo->hResItem,
+													 psPerProc->hResManContext);
+
+	if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32							ui32BridgeID,
+				      PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS		*psModifySyncOpsIN,
+					  PVRSRV_BRIDGE_RETURN							*psModifySyncOpsOUT,
+					  PVRSRV_PER_PROCESS_DATA						*psPerProc)
+{
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS);
+
+	psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+													(IMG_VOID**)&psModSyncOpInfo,
+													psModifySyncOpsIN->hKernelSyncInfoModObj,
+													PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+	if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+	{
+		/* Empty */
+		psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	psModifySyncOpsOUT->eError = DoModifyCompleteSyncOps(psModSyncOpInfo);
+
+	if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: DoModifyCompleteSyncOps failed"));
+		return 0;
+	}
+
+	PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
+	psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+
+	/* re-kick all services managed devices */
+	PVRSRVScheduleDeviceCallbacks();
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsTakeTokenBW(IMG_UINT32									ui32BridgeID,
+						 PVRSRV_BRIDGE_IN_SYNC_OPS_TAKE_TOKEN       *psSyncOpsTakeTokenIN,
+						 PVRSRV_BRIDGE_OUT_SYNC_OPS_TAKE_TOKEN      *psSyncOpsTakeTokenOUT,
+						 PVRSRV_PER_PROCESS_DATA					*psPerProc)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_TAKE_TOKEN);
+
+	psSyncOpsTakeTokenOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+													   (IMG_VOID**)&psKernelSyncInfo,
+													   psSyncOpsTakeTokenIN->hKernelSyncInfo,
+													   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if (psSyncOpsTakeTokenOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsTakeTokenBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	/* We return PRE-INCREMENTED versions of all sync Op Values */
+
+	psSyncOpsTakeTokenOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+	psSyncOpsTakeTokenOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+	psSyncOpsTakeTokenOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToTokenBW(IMG_UINT32                                         ui32BridgeID,
+							PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_TOKEN		   *psSyncOpsFlushToTokenIN,
+							PVRSRV_BRIDGE_RETURN						       *psSyncOpsFlushToTokenOUT,
+							PVRSRV_PER_PROCESS_DATA		   		               *psPerProc)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	IMG_UINT32 ui32ReadOpsPendingSnapshot;
+	IMG_UINT32 ui32WriteOpsPendingSnapshot;
+	IMG_UINT32 ui32ReadOps2PendingSnapshot;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN);
+
+	psSyncOpsFlushToTokenOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+														  (IMG_VOID**)&psKernelSyncInfo,
+														  psSyncOpsFlushToTokenIN->hKernelSyncInfo,
+														  PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if (psSyncOpsFlushToTokenOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToTokenBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	ui32ReadOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOpsPendingSnapshot;
+	ui32WriteOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32WriteOpsPendingSnapshot;
+	ui32ReadOps2PendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOps2PendingSnapshot;
+
+	psSyncOpsFlushToTokenOUT->eError = DoQuerySyncOpsSatisfied(psKernelSyncInfo,
+															   ui32ReadOpsPendingSnapshot,
+															   ui32WriteOpsPendingSnapshot,
+															   ui32ReadOps2PendingSnapshot);
+
+	if (psSyncOpsFlushToTokenOUT->eError != PVRSRV_OK && psSyncOpsFlushToTokenOUT->eError != PVRSRV_ERROR_RETRY)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToTokenBW: DoQuerySyncOpsSatisfied failed"));
+		return 0;
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToModObjBW(IMG_UINT32                                         ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ		    *psSyncOpsFlushToModObjIN,
+							 PVRSRV_BRIDGE_RETURN						        *psSyncOpsFlushToModObjOUT,
+							 PVRSRV_PER_PROCESS_DATA		   		            *psPerProc)
+{
+	MODIFY_SYNC_OP_INFO		*psModSyncOpInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ);
+
+	psSyncOpsFlushToModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+														   (IMG_VOID**)&psModSyncOpInfo,
+														   psSyncOpsFlushToModObjIN->hKernelSyncInfoModObj,
+														   PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+	if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+	{
+		/* Empty */
+		psSyncOpsFlushToModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+	psSyncOpsFlushToModObjOUT->eError = DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
+																psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+																psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+																psModSyncOpInfo->ui32ReadOps2PendingSnapShot);
+
+	if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK && psSyncOpsFlushToModObjOUT->eError != PVRSRV_ERROR_RETRY)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: DoQuerySyncOpsSatisfied failed"));
+		return 0;
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToDeltaBW(IMG_UINT32                                         ui32BridgeID,
+							PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA		   *psSyncOpsFlushToDeltaIN,
+							PVRSRV_BRIDGE_RETURN						       *psSyncOpsFlushToDeltaOUT,
+							PVRSRV_PER_PROCESS_DATA		   		               *psPerProc)
+{
+	PVRSRV_KERNEL_SYNC_INFO		*psSyncInfo;
+	IMG_UINT32 ui32DeltaRead;
+	IMG_UINT32 ui32DeltaWrite;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA);
+
+	psSyncOpsFlushToDeltaOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+														  (IMG_VOID**)&psSyncInfo,
+														  psSyncOpsFlushToDeltaIN->hKernelSyncInfo,
+														  PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if (psSyncOpsFlushToDeltaOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToDeltaBW: PVRSRVLookupHandle failed"));
+		return 0;
+	}
+
+	/* FIXME:  there's logic here in the bridge-wrapper - this needs to be moved to
+	   a better place */
+
+	ui32DeltaRead = psSyncInfo->psSyncData->ui32ReadOpsPending - psSyncInfo->psSyncData->ui32ReadOpsComplete;
+	ui32DeltaWrite = psSyncInfo->psSyncData->ui32WriteOpsPending - psSyncInfo->psSyncData->ui32WriteOpsComplete;
+
+	if (ui32DeltaRead <= psSyncOpsFlushToDeltaIN->ui32Delta && ui32DeltaWrite <= psSyncOpsFlushToDeltaIN->ui32Delta)
+	{
+#if defined(PDUMP) && !defined(SUPPORT_VGX)
+		/* pdump the sync pol: reads */
+		PDumpComment("Poll for read ops complete to delta (%u)",
+					 psSyncOpsFlushToDeltaIN->ui32Delta);
+		psSyncOpsFlushToDeltaOUT->eError =
+			PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+						  offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+						  psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+						  0xFFFFFFFF,
+						  PDUMP_POLL_OPERATOR_GREATEREQUAL,
+						  0,
+						  MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+		/* pdump the sync pol: writes */
+		PDumpComment("Poll for write ops complete to delta (%u)",
+					 psSyncOpsFlushToDeltaIN->ui32Delta);
+		psSyncOpsFlushToDeltaOUT->eError =
+			PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+						  offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+						  psSyncInfo->psSyncData->ui32LastOpDumpVal,
+						  0xFFFFFFFF,
+						  PDUMP_POLL_OPERATOR_GREATEREQUAL,
+						  0,
+						  MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+		psSyncOpsFlushToDeltaOUT->eError = PVRSRV_OK;
+	}
+	else
+	{
+		psSyncOpsFlushToDeltaOUT->eError = PVRSRV_ERROR_RETRY;
+	}
+
+	return 0;
+}
+
+
+static PVRSRV_ERROR
+FreeSyncInfoCallback(IMG_PVOID	pvParam,
+                     IMG_UINT32 ui32Param,
+                     IMG_BOOL	bDummy)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+    PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pvParam;
+
+	PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
+
+	return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVAllocSyncInfoBW(IMG_UINT32                                         ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO                  *psAllocSyncInfoIN,
+					  PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO                 *psAllocSyncInfoOUT,
+					  PVRSRV_PER_PROCESS_DATA		   		            *psPerProc)
+{
+	PVRSRV_KERNEL_SYNC_INFO		*psSyncInfo;
+	PVRSRV_ERROR eError;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_HANDLE hDevMemContext;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SYNC_INFO);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psAllocSyncInfoOUT->eError, psPerProc, 1)
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_HANDLE *)&psDeviceNode,
+								psAllocSyncInfoIN->hDevCookie,
+								PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(eError != PVRSRV_OK)
+	{
+		goto allocsyncinfo_errorexit;
+	}
+
+	hDevMemContext = psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+	eError = PVRSRVAllocSyncInfoKM(psDeviceNode,
+								   hDevMemContext,
+								   &psSyncInfo);
+
+	if (eError != PVRSRV_OK)
+	{
+		goto allocsyncinfo_errorexit;
+	}
+
+	eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+							   &psAllocSyncInfoOUT->hKernelSyncInfo,
+							   psSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO,
+							   PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+	if(eError != PVRSRV_OK)
+	{
+		goto allocsyncinfo_errorexit_freesyncinfo;
+	}
+
+	psSyncInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+											   RESMAN_TYPE_SYNC_INFO,
+											   psSyncInfo,
+											   0,
+											   &FreeSyncInfoCallback);
+
+	/* Success */
+	goto allocsyncinfo_commit;
+
+	/* Error handling */
+ allocsyncinfo_errorexit_freesyncinfo:
+	PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
+
+ allocsyncinfo_errorexit:
+
+	/* Common exit */
+ allocsyncinfo_commit:
+	psAllocSyncInfoOUT->eError = eError;
+	COMMIT_HANDLE_BATCH_OR_ERROR(eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+PVRSRVFreeSyncInfoBW(IMG_UINT32                                          ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_FREE_SYNC_INFO                     *psFreeSyncInfoIN,
+					 PVRSRV_BRIDGE_RETURN                                *psFreeSyncInfoOUT,
+					 PVRSRV_PER_PROCESS_DATA		   		             *psPerProc)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+	PVRSRV_ERROR eError;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SYNC_INFO);
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID**)&psSyncInfo,
+								psFreeSyncInfoIN->hKernelSyncInfo,
+								PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVLookupHandle failed"));
+		psFreeSyncInfoOUT->eError = eError;
+		return 0;
+	}
+
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								 psFreeSyncInfoIN->hKernelSyncInfo,
+								 PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVReleaseHandle failed"));
+		psFreeSyncInfoOUT->eError = eError;
+		return 0;
+	}
+
+    eError = ResManFreeResByPtr(psSyncInfo->hResItem, CLEANUP_WITH_POLL);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: ResManFreeResByPtr failed"));
+		psFreeSyncInfoOUT->eError = eError;
+		return 0;
+	}
+
+	return 0;
+}
+
+
+PVRSRV_ERROR
+CommonBridgeInit(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DEVICES, PVRSRVEnumerateDevicesBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO, PVRSRVAcquireDeviceDataBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_DEVICEINFO, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT, PVRSRVCreateDeviceMemContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT, PVRSRVDestroyDeviceMemContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO, PVRSRVGetDeviceMemHeapInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_DEVICEMEM, PVRSRVAllocDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEVICEMEM, PVRSRVFreeDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GETFREE_DEVICEMEM, PVRSRVGetFreeDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_COMMANDQUEUE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA, PVRMMapOSMemHandleToMMapDataBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CONNECT_SERVICES, PVRSRVConnectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DISCONNECT_SERVICES, PVRSRVDisconnectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_DEVICE_MEM, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVICEMEMINFO, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM	, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEV_VIRTMEM, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_EXT_MEMORY, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_EXT_MEMORY, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY, PVRSRVMapDeviceMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEV_MEMORY, PVRSRVUnmapDeviceMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM, PVRSRVExportDeviceMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MMAP_DATA, PVRMMapReleaseMMapDataBW);
+    SetDispatchTableEntry(PVRSRV_BRIDGE_CHG_DEV_MEM_ATTRIBS, PVRSRVChangeDeviceMemoryAttributesBW);
+    SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY_2, PVRSRVMapDeviceMemoryBW);
+    SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2, PVRSRVExportDeviceMemBW);
+#if defined(SUPPORT_ION)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_ION_HANDLE, PVRSRVMapIonHandleBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_ION_HANDLE, PVRSRVUnmapIonHandleBW);
+#endif
+#if defined(SUPPORT_DMABUF)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DMABUF, PVRSRVMapDmaBufBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DMABUF, PVRSRVUnmapDmaBufBW);
+#endif
+
+	/* SIM */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+
+	/* User Mapping */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
+
+	/* API to retrieve misc. info. from services */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
+
+	/* Overlay ioctls */
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES, DummyBW);
+#endif
+
+
+	/* PDUMP */
+#if defined(PDUMP)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPMEM, PDumpMemBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REG, PDumpRegWithFlagsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REGPOL, PDumpRegPolBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_COMMENT, PDumpCommentBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SETFRAME, PDumpSetFrameBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_ISCAPTURING, PDumpIsCaptureFrameBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPBITMAP, PDumpBitmapBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPREADREG, PDumpReadRegBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SYNCPOL, PDumpSyncPolBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPAGES, PDumpMemPagesBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DRIVERINFO, PDumpDriverInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR, PDumpPDDevPAddrBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW);
+#endif /* defined(PDUMP) */
+
+	/* DisplayClass APIs */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY, PVRSRVMapDeviceClassMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY, PVRSRVUnmapDeviceClassMemoryBW);
+
+	/* device class enum */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
+
+	/* display class API */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE, PVRSRVOpenDCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE, PVRSRVCloseDCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS, PVRSRVEnumDCFormatsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS, PVRSRVEnumDCDimsBW);
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+#else
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, DummyBW);
+#endif
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO, PVRSRVGetDCInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN, PVRSRVCreateDCSwapChainBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN, PVRSRVDestroyDCSwapChainBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT, PVRSRVSetDCDstRectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT, PVRSRVSetDCSrcRectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY, PVRSRVSetDCDstColourKeyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2, PVRSRVSwapToDCBuffer2BW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
+
+	/* buffer class API */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE, PVRSRVOpenBCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE, PVRSRVCloseBCDeviceBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO, PVRSRVGetBCInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER, PVRSRVGetBCBufferBW);
+#else /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY, DummyBW);
+
+	/* device class enum */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, DummyBW);
+
+	/* display class API */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM, DummyBW);
+
+	/* buffer class API */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER, DummyBW);
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+	/* Wrap/Unwrap external memory */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
+
+	/* Shared memory */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
+
+	/* Intialisation Service support */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT,	&PVRSRVInitSrvConnectBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT, &PVRSRVInitSrvDisconnectBW);
+
+	/* Event Object */
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT,	&PVRSRVEventObjectWaitBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN,	&PVRSRVEventObjectOpenBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE, &PVRSRVEventObjectCloseBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ, PVRSRVCreateSyncInfoModObjBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ, PVRSRVDestroySyncInfoModObjBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS, PVRSRVModifyPendingSyncOpsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS, PVRSRVModifyCompleteSyncOpsBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_TAKE_TOKEN, PVRSRVSyncOpsTakeTokenBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN, PVRSRVSyncOpsFlushToTokenBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ, PVRSRVSyncOpsFlushToModObjBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA, PVRSRVSyncOpsFlushToDeltaBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SYNC_INFO, PVRSRVAllocSyncInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SYNC_INFO, PVRSRVFreeSyncInfoBW);
+
+#if defined (SUPPORT_SGX)
+	SetSGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_VGX)
+	SetVGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_MSVDX)
+	SetMSVDXDispatchTableEntry();
+#endif
+
+	/* A safety net to help ensure there won't be any un-initialised dispatch
+	 * table entries... */
+	/* Note: This is specifically done _after_ setting all the dispatch entries
+	 * so that SetDispatchTableEntry can detect mistakes where entries
+	 * overlap */
+	for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
+	{
+		if(!g_BridgeDispatchTable[i].pfFunction)
+		{
+			g_BridgeDispatchTable[i].pfFunction = &DummyBW;
+#if defined(DEBUG_BRIDGE_KM)
+			g_BridgeDispatchTable[i].pszIOCName = "_PVRSRV_BRIDGE_DUMMY";
+			g_BridgeDispatchTable[i].pszFunctionName = "DummyBW";
+			g_BridgeDispatchTable[i].ui32CallCount = 0;
+			g_BridgeDispatchTable[i].ui32CopyFromUserTotalBytes = 0;
+			g_BridgeDispatchTable[i].ui32CopyToUserTotalBytes = 0;
+#endif
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+					  PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM)
+{
+	IMG_VOID   * psBridgeIn;
+	IMG_VOID   * psBridgeOut;
+	BridgeWrapperFunction pfBridgeHandler;
+	IMG_UINT32   ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+	IMG_INT      err          = -EFAULT;
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+	PVR_DPF((PVR_DBG_ERROR, "%s: %s",
+			 __FUNCTION__,
+			 g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+	g_BridgeDispatchTable[ui32BridgeID].ui32CallCount++;
+	g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+	if(!psPerProc->bInitProcess)
+	{
+		if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+		{
+			if(!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed.  Driver unusable.",
+						 __FUNCTION__));
+				goto return_fault;
+			}
+		}
+		else
+		{
+			if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation is in progress",
+						 __FUNCTION__));
+				goto return_fault;
+			}
+			else
+			{
+				/* Only certain operations are allowed */
+				switch(ui32BridgeID)
+				{
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_DISCONNECT_SERVICES):
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_CONNECT):
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_DISCONNECT):
+					case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_UM_KM_COMPAT_CHECK):
+						break;
+					default:
+						PVR_DPF((PVR_DBG_ERROR, "%s: Driver initialisation not completed yet.",
+								 __FUNCTION__));
+						goto return_fault;
+				}
+			}
+		}
+	}
+
+#if defined(__linux__)
+	{
+		/* This should be moved into the linux specific code */
+		SYS_DATA *psSysData;
+
+		SysAcquireData(&psSysData);
+
+		/* We have already set up some static buffers to store our ioctl data... */
+		psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
+		psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+		/* check we are not using a bigger bridge than allocated */
+		if((psBridgePackageKM->ui32InBufferSize > PVRSRV_MAX_BRIDGE_IN_SIZE) || 
+			(psBridgePackageKM->ui32OutBufferSize > PVRSRV_MAX_BRIDGE_OUT_SIZE))
+		{
+			goto return_fault;
+		}
+
+
+		if(psBridgePackageKM->ui32InBufferSize > 0)
+		{
+			if(!OSAccessOK(PVR_VERIFY_READ,
+							psBridgePackageKM->hParamIn,
+							psBridgePackageKM->ui32InBufferSize))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Invalid pvParamIn pointer", __FUNCTION__));
+			}
+
+			if(CopyFromUserWrapper(psPerProc,
+					               ui32BridgeID,
+								   psBridgeIn,
+								   psBridgePackageKM->hParamIn,
+								   psBridgePackageKM->ui32InBufferSize)
+			  != PVRSRV_OK)
+			{
+				goto return_fault;
+			}
+		}
+	}
+#else
+	psBridgeIn  = (IMG_VOID*)(IMG_UINTPTR_T)psBridgePackageKM->hParamIn;
+	psBridgeOut = (IMG_VOID*)(IMG_UINTPTR_T)psBridgePackageKM->hParamOut;
+#endif
+
+	if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
+				 __FUNCTION__, ui32BridgeID));
+		goto return_fault;
+	}
+
+	if( ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_UM_KM_COMPAT_CHECK))
+		PVRSRVCompatCheckKM(psBridgeIn, psBridgeOut);
+	else
+	{
+		pfBridgeHandler =
+			(BridgeWrapperFunction)g_BridgeDispatchTable[ui32BridgeID].pfFunction;
+		err = pfBridgeHandler(ui32BridgeID,
+						  psBridgeIn,
+						  psBridgeOut,
+						  psPerProc);
+		if(err < 0)
+		{
+			goto return_fault;
+		}
+	}
+
+#if defined(__linux__)
+	/* This should be moved into the linux specific code */
+	if(CopyToUserWrapper(psPerProc,
+						 ui32BridgeID,
+						 psBridgePackageKM->hParamOut,
+						 psBridgeOut,
+						 psBridgePackageKM->ui32OutBufferSize)
+	   != PVRSRV_OK)
+	{
+		goto return_fault;
+	}
+#endif
+
+	err = 0;
+return_fault:
+
+	ReleaseHandleBatch(psPerProc);
+	return err;
+}
+
+/******************************************************************************
+ End of file (bridged_pvr_bridge.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
new file mode 100644
index 0000000..0a1cc6e
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_pvr_bridge.h
@@ -0,0 +1,257 @@
+/*************************************************************************/ /*!
+@Title          PVR Bridge Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the PVR Bridge code
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X)	_IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X)	((X) - PVRSRV_IOWR(PVRSRV_BRIDGE_UMKM_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM	12
+#endif
+#ifndef EFAULT
+#define EFAULT	14
+#endif
+#ifndef ENOTTY
+#define ENOTTY	25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+					IMG_UINT32 ui32BridgeID,
+					IMG_VOID *pvDest,
+					IMG_VOID *pvSrc,
+					IMG_UINT32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData, 
+				  IMG_UINT32 ui32BridgeID,
+				  IMG_VOID *pvDest,
+				  IMG_VOID *pvSrc,
+				  IMG_UINT32 ui32Size);
+#else
+#define CopyFromUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+	OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+	OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size)
+#endif
+
+
+#define ASSIGN_AND_RETURN_ON_ERROR(error, src, res)		\
+	do							\
+	{							\
+		(error) = (src);				\
+		if ((error) != PVRSRV_OK) 			\
+		{						\
+			return (res);				\
+		}						\
+	} while ((error) != PVRSRV_OK);
+
+#define ASSIGN_AND_EXIT_ON_ERROR(error, src)		\
+	ASSIGN_AND_RETURN_ON_ERROR(error, src, 0)
+
+#if defined(PVR_SECURE_HANDLES)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NewHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+NewHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc,
+					IMG_UINT32 ui32BatchSize)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+	eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+	if (eError == PVRSRV_OK)
+	{
+		psPerProc->bHandlesBatched = IMG_TRUE;
+	}
+
+	return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)	\
+	ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, ui32BatchSize))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(CommitHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+CommitHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVR_ASSERT(psPerProc->bHandlesBatched);
+
+	psPerProc->bHandlesBatched = IMG_FALSE;
+
+	return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc) 			\
+	ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReleaseHandleBatch)
+#endif
+static INLINE IMG_VOID
+ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	if (psPerProc->bHandlesBatched)
+	{
+		psPerProc->bHandlesBatched = IMG_FALSE;
+
+		PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+	}
+}
+#else	/* defined(PVR_SECURE_HANDLES) */
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
+#define ReleaseHandleBatch(psPerProc)
+#endif	/* defined(PVR_SECURE_HANDLES) */
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+		IMG_VOID *psBridgeIn,
+		IMG_VOID *psBridgeOut,
+		PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
+									 IMG_VOID *psBridgeIn,
+									 IMG_VOID *psBridgeOut,
+									 PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+	BridgeWrapperFunction pfFunction; /*!< The wrapper function that validates the ioctl
+										arguments before calling into srvkm proper */
+#if defined(DEBUG_BRIDGE_KM)
+	const IMG_CHAR *pszIOCName; /*!< Name of the ioctl: e.g. "PVRSRV_BRIDGE_CONNECT_SERVICES" */
+	const IMG_CHAR *pszFunctionName; /*!< Name of the wrapper function: e.g. "PVRSRVConnectBW" */
+	IMG_UINT32 ui32CallCount; /*!< The total number of times the ioctl has been called */
+	IMG_UINT32 ui32CopyFromUserTotalBytes; /*!< The total number of bytes copied from
+											 userspace within this ioctl */
+	IMG_UINT32 ui32CopyToUserTotalBytes; /*!< The total number of bytes copied from
+										   userspace within this ioctl */
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+	#if defined(SUPPORT_VGX)
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_VGX_CMD
+	#else
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_MSVDX_CMD
+	#endif
+#else
+	#if defined(SUPPORT_SGX)
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_SGX_CMD
+	#else
+		#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+		#define PVRSRV_BRIDGE_LAST_DEVICE_CMD	   PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+	#endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+					   const IMG_CHAR *pszIOCName,
+					   BridgeWrapperFunction pfFunction,
+					   const IMG_CHAR *pszFunctionName);
+
+
+/* PRQA S 0884,3410 2*/ /* macro relies on the lack of brackets */
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+	_SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+	IMG_UINT32 ui32IOCTLCount;
+	IMG_UINT32 ui32TotalCopyFromUserBytes;
+	IMG_UINT32 ui32TotalCopyToUserBytes;
+}PVRSRV_BRIDGE_GLOBAL_STATS;
+
+/* OS specific code way want to report the stats held here and within the
+ * BRIDGE_DISPATCH_TABLE_ENTRYs (E.g. on Linux we report these via a
+ * proc entry /proc/pvr/bridge_stats. Ref printLinuxBridgeStats()) */
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+PVRSRV_ERROR CommonBridgeInit(IMG_VOID);
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+					  PVRSRV_BRIDGE_PACKAGE   * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __BRIDGED_PVR_BRIDGE_H__ */
+
+/******************************************************************************
+ End of file (bridged_pvr_bridge.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/bridged/bridged_support.c b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_support.c
new file mode 100644
index 0000000..2ccdc66
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_support.c
@@ -0,0 +1,113 @@
+/*************************************************************************/ /*!
+@Title          PVR Bridge Support Functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    User/kernel mode bridge support.  The functions in here
+                may be used beyond the bridge code proper (e.g. Linux
+                mmap interface).
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "img_defs.h"
+#include "servicesint.h"
+#include "bridged_support.h"
+
+
+/*
+ * Derive the internal OS specific memory handle from a secure
+ * handle.
+ */
+PVRSRV_ERROR
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle)
+{
+	IMG_HANDLE hMHandleInt;
+	PVRSRV_HANDLE_TYPE eHandleType;
+	PVRSRV_ERROR eError;
+
+	/*
+	 * We don't know the type of the handle at this point, so we use
+	 * PVRSRVLookupHandleAnyType to look it up.
+	 */
+	eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+							  &eHandleType,
+							  hMHandle);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	switch(eHandleType)
+	{
+#if defined(PVR_SECURE_HANDLES)
+		case PVRSRV_HANDLE_TYPE_MEM_INFO:
+		case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+		case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+		{
+			PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hMHandleInt;
+
+			*phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+			break;
+		}
+		case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+		{
+			PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hMHandleInt;
+			PVRSRV_KERNEL_MEM_INFO *psMemInfo = psSyncInfo->psSyncDataMemInfoKM;
+			
+			*phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+			break;
+		}
+		case  PVRSRV_HANDLE_TYPE_SOC_TIMER:
+		{
+			*phOSMemHandle = (IMG_VOID *)hMHandleInt;
+			break;
+		}
+#else
+		case  PVRSRV_HANDLE_TYPE_NONE:
+			*phOSMemHandle = (IMG_VOID *)hMHandleInt;
+			break;
+#endif
+		default:
+			return PVRSRV_ERROR_BAD_MAPPING;
+	}
+
+	return PVRSRV_OK;
+}
+/******************************************************************************
+ End of file (bridged_support.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/bridged/bridged_support.h b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_support.h
new file mode 100644
index 0000000..e32fa88
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/bridged/bridged_support.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@Title          PVR Bridge Support
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    User/kernel mode bridge support.  The functions in here
+                may be used beyond the bridge code proper (e.g. Linux
+                mmap interface).
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __BRIDGED_SUPPORT_H__
+#define __BRIDGED_SUPPORT_H__
+
+#include "handle.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Derive the internal OS specific memory handle from a secure
+ * handle.
+ */
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __BRIDGED_SUPPORT_H__ */
+
+/******************************************************************************
+ End of file (bridged_support.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c b/drivers/gpu/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
new file mode 100644
index 0000000..d0a10ad
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
@@ -0,0 +1,3058 @@
+/*************************************************************************/ /*!
+@Title          SGX Common Bridge Module (kernel side)
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Receives calls from the user portion of services and
+                despatches them to functions in the kernel portion.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+
+#if defined(SUPPORT_SGX)
+
+#include "services.h"
+#include "pvr_debug.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "power.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "sgx_options.h"
+
+#if defined(SUPPORT_MSVDX)
+	#include "msvdx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+
+static IMG_INT
+SGXGetClientInfoBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+				   PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO);
+
+	psGetClientInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psGetClientInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psGetClientInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psGetClientInfoOUT->eError =
+		SGXGetClientInfoKM(hDevCookieInt,
+						   &psGetClientInfoOUT->sClientInfo);
+	return 0;
+}
+
+static IMG_INT
+SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+					   PVRSRV_BRIDGE_RETURN *psRetOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psReleaseClientInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+	PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+	/* 
+	 * psDevInfo->ui32ClientRefCount can be zero if an error occurred before SGXGetClientInfo is called
+	 */
+	if (psDevInfo->ui32ClientRefCount > 0)
+	{
+		psDevInfo->ui32ClientRefCount--;
+	}
+	
+	psRetOUT->eError = PVRSRV_OK;
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID,
+						PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+						PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+						PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO);
+
+	psSGXGetInternalDevInfoOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXGetInternalDevInfoIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXGetInternalDevInfoOUT->eError =
+		SGXGetInternalDevInfoKM(hDevCookieInt,
+								&psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
+
+	/*
+	 * Handle is not allocated in batch mode, as there is no resource
+	 * allocation to undo if the handle allocation fails.
+	 */
+	psSGXGetInternalDevInfoOUT->eError =
+		PVRSRVAllocHandle(psPerProc->psHandleBase,
+						  &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+						  psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+						  PVRSRV_HANDLE_TYPE_MEM_INFO,
+						  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXDoKickBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_UINT32 i;
+	IMG_INT ret = 0;
+	IMG_UINT32 ui32NumDstSyncs;
+	IMG_HANDLE *phKernelSyncInfoHandles = IMG_NULL;
+	IMG_HANDLE *pahDstSyncHandles;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psDoKickIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+						   psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if(psDoKickIN->sCCBKick.hTA3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.hTA3DSyncInfo,
+							   psDoKickIN->sCCBKick.hTA3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if(psDoKickIN->sCCBKick.hTASyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.hTASyncInfo,
+							   psDoKickIN->sCCBKick.hTASyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+#if defined(FIX_HW_BRN_31620)
+	/* We need to lookup the mem context and pass it through */
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psDoKickIN->sCCBKick.hDevMemContext,
+						   psDoKickIN->sCCBKick.hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+#endif
+
+	if(psDoKickIN->sCCBKick.h3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.h3DSyncInfo,
+							   psDoKickIN->sCCBKick.h3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	/* texture dependency details */
+	if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS_TA)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+
+#if !(defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE))
+	for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+							   psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+#endif /* !defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+	if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++)
+	{
+		psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+							   psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+
+#else
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+							   psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++)
+	{
+		psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+							   psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+							   
+#else
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+							   psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+
+	if(ui32NumDstSyncs > 0)
+	{
+		if(!OSAccessOK(PVR_VERIFY_READ,
+						(IMG_HANDLE*)psDoKickIN->sCCBKick.hDstSyncHandles,
+						ui32NumDstSyncs * sizeof(IMG_HANDLE)))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:"
+					" Invalid pasDstSyncHandles pointer", __FUNCTION__));
+			return -EFAULT;
+		}
+
+		psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+										ui32NumDstSyncs * sizeof(IMG_HANDLE),
+										(IMG_VOID **)&phKernelSyncInfoHandles,
+										0,
+										"Array of Synchronization Info Handles");
+		if (psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+
+		if(CopyFromUserWrapper(psPerProc,
+							ui32BridgeID,
+							phKernelSyncInfoHandles,
+							(IMG_HANDLE*)psDoKickIN->sCCBKick.hDstSyncHandles,
+							ui32NumDstSyncs * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+		{
+			ret = -EFAULT;
+			goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+		}
+
+		/* Set sCCBKick.hDstSyncHandles to point to the local memory */
+		psDoKickIN->sCCBKick.hDstSyncHandles = (IMG_HANDLE)phKernelSyncInfoHandles;
+		pahDstSyncHandles = psDoKickIN->sCCBKick.hDstSyncHandles;
+		for( i = 0; i < ui32NumDstSyncs; i++)
+		{
+			psRetOUT->eError =
+				PVRSRVLookupHandle(psPerProc->psHandleBase,
+									&pahDstSyncHandles[i],
+									pahDstSyncHandles[i],
+									PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+			if(psRetOUT->eError != PVRSRV_OK)
+			{
+				goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+			}
+
+		}
+
+		psRetOUT->eError =
+					PVRSRVLookupHandle(psPerProc->psHandleBase,
+									   &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+									   psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+									   PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+		}
+	}
+
+	psRetOUT->eError =
+		SGXDoKickKM(hDevCookieInt,
+					&psDoKickIN->sCCBKick);
+
+PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+
+	if(phKernelSyncInfoHandles)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32NumDstSyncs * sizeof(IMG_HANDLE),
+				  (IMG_VOID *)phKernelSyncInfoHandles,
+				  0);
+		/*not nulling pointer, out of scope*/
+	}
+	return ret;
+}
+
+
+static IMG_INT
+SGXScheduleProcessQueuesBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psScheduleProcQIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt);
+
+	return 0;
+}
+
+
+#if defined(TRANSFER_QUEUE)
+static IMG_INT
+SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_TRANSFER_SGX_KICK *psKick;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	psKick = &psSubmitTransferIN->sKick;
+
+#if defined(FIX_HW_BRN_31620)
+	/* We need to lookup the mem context and pass it through */
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psKick->hDevMemContext,
+						   psKick->hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+#endif
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSubmitTransferIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psKick->hCCBMemInfo,
+						   psKick->hCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->hTASyncInfo,
+							   psKick->hTASyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->h3DSyncInfo,
+							   psKick->h3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->ahSrcSyncInfo[i],
+							   psKick->ahSrcSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psKick->ui32NumDstSync; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->ahDstSyncInfo[i],
+							   psKick->ahDstSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick);
+
+	return 0;
+}
+
+static IMG_INT
+SGXSetTransferContextPriorityBW(IMG_UINT32 ui32BridgeID,
+                        PVRSRV_BRIDGE_IN_SGX_SET_TRANSFER_CONTEXT_PRIORITY *psSGXSetTransferContextPriorityIN,
+                        PVRSRV_BRIDGE_RETURN *psRetOUT,
+                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+    IMG_HANDLE hTransferContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SET_TRANSFER_CONTEXT_PRIORITY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXSetTransferContextPriorityIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hTransferContextInt,
+						   psSGXSetTransferContextPriorityIN->hHWTransferContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+    psRetOUT->eError = SGXSetTransferContextPriorityKM(
+            hDevCookieInt, 
+            hTransferContextInt,
+            psSGXSetTransferContextPriorityIN->ui32Priority,
+            psSGXSetTransferContextPriorityIN->ui32OffsetOfPriorityField);
+
+    return 0;
+}
+
+static IMG_INT
+SGXSetRenderContextPriorityBW(IMG_UINT32 ui32BridgeID,
+                        PVRSRV_BRIDGE_IN_SGX_SET_RENDER_CONTEXT_PRIORITY *psSGXSetRenderContextPriorityIN,
+                        PVRSRV_BRIDGE_RETURN *psRetOUT,
+                        PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+    IMG_HANDLE hRenderContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SET_RENDER_CONTEXT_PRIORITY);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXSetRenderContextPriorityIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hRenderContextInt,
+						   psSGXSetRenderContextPriorityIN->hHWRenderContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+    psRetOUT->eError = SGXSetRenderContextPriorityKM(
+            hDevCookieInt, 
+            hRenderContextInt,
+            psSGXSetRenderContextPriorityIN->ui32Priority,
+            psSGXSetRenderContextPriorityIN->ui32OffsetOfPriorityField);
+
+    return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
+			PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN,
+			PVRSRV_BRIDGE_RETURN *psRetOUT,
+			PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_2D_SGX_KICK   *psKick;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D);
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+	psKick = &psSubmit2DIN->sKick;
+
+#if defined(FIX_HW_BRN_31620)
+	/* We need to lookup the mem context and pass it through */
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psKick->hDevMemContext,
+						   psKick->hDevMemContext,
+						   PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+#endif
+
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSubmit2DIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &psKick->hCCBMemInfo,
+						   psKick->hCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->hTASyncInfo,
+							   psKick->hTASyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->h3DSyncInfo,
+							   psKick->h3DSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS)
+	{
+		psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+		return 0;
+	}
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->ahSrcSyncInfo[i],
+							   psKick->ahSrcSyncInfo[i],
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	if (psKick->hDstSyncInfo != IMG_NULL)
+	{
+		psRetOUT->eError =
+			PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &psKick->hDstSyncInfo,
+							   psKick->hDstSyncInfo,
+							   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	psRetOUT->eError =
+		SGXSubmit2DKM(hDevCookieInt, psKick);
+
+	return 0;
+}
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
+#endif /* #if defined(TRANSFER_QUEUE) */
+
+
+static IMG_INT
+SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+				 PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+				 PVRSRV_BRIDGE_RETURN *psRetOUT,
+				 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hDevMemContextInt = 0;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	SGX_MISC_INFO        sMiscInfo;
+ 	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+							PVRSRV_BRIDGE_SGX_GETMISCINFO);
+
+	psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+							&hDevCookieInt,
+							psSGXGetMiscInfoIN->hDevCookie,
+							PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	/* Lookup handle for dev mem context */
+	if (((SGX_MISC_INFO*)psSGXGetMiscInfoIN->hMiscInfo)->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
+	{
+		psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								&hDevMemContextInt,
+								((SGX_MISC_INFO*)psSGXGetMiscInfoIN->hMiscInfo)->hDevMemContext,
+								PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+		if(psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+#endif
+	/* device node is required for scheduling a CCB command */
+	psDeviceNode = hDevCookieInt;
+	PVR_ASSERT(psDeviceNode != IMG_NULL);
+	if (psDeviceNode == IMG_NULL)
+	{
+		return -EFAULT;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	/* Copy psMiscInfo to kernel space */
+	psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+			                               ui32BridgeID,
+			                               &sMiscInfo,
+			                               (SGX_MISC_INFO*)psSGXGetMiscInfoIN->hMiscInfo,
+			                               sizeof(SGX_MISC_INFO));
+	if (psRetOUT->eError != PVRSRV_OK)
+	{
+		return -EFAULT;
+	}
+
+	{
+		psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt);
+
+		if (psRetOUT->eError != PVRSRV_OK)
+		{
+			return 0;
+		}
+	}
+
+	/* Copy back misc info to user address space */
+	psRetOUT->eError = CopyToUserWrapper(psPerProc,
+		                             ui32BridgeID,
+		                             (SGX_MISC_INFO*)psSGXGetMiscInfoIN->hMiscInfo,
+		                             &sMiscInfo,
+		                             sizeof(SGX_MISC_INFO));
+	if (psRetOUT->eError != PVRSRV_OK)
+	{
+		return -EFAULT;
+	}
+	return 0;
+}
+
+
+static IMG_INT
+SGXReadHWPerfCBBW(IMG_UINT32							ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB	*psSGXReadHWPerfCBIN,
+				  PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB	*psSGXReadHWPerfCBOUT,
+				  PVRSRV_PER_PROCESS_DATA				*psPerProc)
+{
+	IMG_HANDLE					hDevCookieInt;
+	PVRSRV_SGX_HWPERF_CB_ENTRY	*psAllocated, *psHWPerfCBData;
+	IMG_HANDLE					hAllocatedHandle;
+	IMG_UINT32					ui32AllocatedSize;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB);
+
+	psSGXReadHWPerfCBOUT->eError =PVRSRVLookupHandle(psPerProc->psHandleBase,
+							&hDevCookieInt,
+							psSGXReadHWPerfCBIN->hDevCookie,
+							PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+	psHWPerfCBData = (PVRSRV_SGX_HWPERF_CB_ENTRY *)psSGXReadHWPerfCBIN->hHWPerfCBData;
+	ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize *
+							sizeof(psHWPerfCBData[0]);
+	ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError,
+	                    OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+	                    ui32AllocatedSize,
+	                    (IMG_VOID **)&psAllocated,
+	                    &hAllocatedHandle,
+						"Array of Hardware Performance Circular Buffer Data"));
+
+	psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt,
+													 psSGXReadHWPerfCBIN->ui32ArraySize,
+													 psAllocated,
+													 &psSGXReadHWPerfCBOUT->ui32DataCount,
+													 &psSGXReadHWPerfCBOUT->ui32ClockSpeed,
+													 &psSGXReadHWPerfCBOUT->ui32HostTimeStamp);
+	if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK)
+	{
+		psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc,
+		                                                 ui32BridgeID,
+		                                                 psHWPerfCBData,
+		                                                 psAllocated,
+		                                                 ui32AllocatedSize);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  ui32AllocatedSize,
+			  psAllocated,
+			  hAllocatedHandle);
+	/*not nulling pointer, out of scope*/
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+				  PVRSRV_BRIDGE_OUT_SGXDEVINITPART2 *psSGXDevInitPart2OUT,
+				  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_ERROR eError;
+	IMG_BOOL bDissociateFailed = IMG_FALSE;
+	IMG_BOOL bLookupFailed = IMG_FALSE;
+	IMG_BOOL bReleaseFailed = IMG_FALSE;
+	IMG_HANDLE hDummy;
+	IMG_UINT32 i;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
+
+	/* Report the kernel-side build options to UM */
+	psSGXDevInitPart2OUT->ui32KMBuildOptions = SGX_BUILD_OPTIONS;
+
+	if(!psPerProc->bInitProcess)
+	{
+		psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+		return 0;
+	}
+
+	psSGXDevInitPart2OUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXDevInitPart2IN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXDevInitPart2OUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+	
+	/* Check all the meminfo handles */
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+#endif
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: Failed to look up HWPerf meminfo (possibly due to SUPPORT_SGX_HWPERF option mismatch)"));
+		bLookupFailed = IMG_TRUE;
+	}
+#endif
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								&hDummy,
+								psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								&hDummy,
+								psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+	
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+#endif
+
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+	defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDummy,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bLookupFailed = IMG_TRUE;
+	}
+#endif
+
+	for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+	{
+		IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+		if (hHandle == IMG_NULL)
+		{
+			continue;
+		}
+
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+							   &hDummy,
+							   hHandle,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+		if (eError != PVRSRV_OK)
+		{
+			bLookupFailed = IMG_TRUE;
+		}
+	}
+
+	if (bLookupFailed)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: A handle lookup failed"));
+		psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+		return 0;
+	}
+
+	/* Lookup and release the device memory handles */
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+#endif
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+#endif
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+										  &psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+										  psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+										  PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+										  &psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+										  psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+										  PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+#endif
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+	defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+						   &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+						   psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+						   PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK)
+	{
+		bReleaseFailed = IMG_TRUE;
+	}
+#endif
+
+	for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+	{
+		IMG_HANDLE *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+		if (*phHandle == IMG_NULL)
+			continue;
+
+		eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+							   phHandle,
+							   *phHandle,
+							   PVRSRV_HANDLE_TYPE_MEM_INFO);
+		if (eError != PVRSRV_OK)
+		{
+			bReleaseFailed = IMG_TRUE;
+		}
+	}
+
+	if (bReleaseFailed)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: A handle release failed"));
+		psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+		/*
+		 * Given that we checked the handles before release, a release
+		 * failure is unexpected.
+		 */
+		PVR_DBG_BREAK;
+		return 0;
+	}
+
+	/* Dissociate device memory from caller */
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+#endif
+
+	/* Dissociate SGX MiscInfo buffer from user space */
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+#endif
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo);
+	if (eError != PVRSRV_OK)
+	{
+		bDissociateFailed = IMG_TRUE;
+	}
+
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAIndexStreamMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPDSMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAUSEMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAParamMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPMPTMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWATPCMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAPSGRgnHdrMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+	defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelVDMStateUpdateBufferMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo);
+	bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+	for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+	{
+		IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+		if (hHandle == IMG_NULL)
+			continue;
+
+		eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle);
+		if (eError != PVRSRV_OK)
+		{
+			bDissociateFailed = IMG_TRUE;
+		}
+	}
+
+	/* If any dissociations failed, free all the device memory passed in */
+	if(bDissociateFailed)
+	{
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXPTLAWriteBackMemInfo);
+#endif
+		PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+
+		for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+		{
+			IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+			if (hHandle == IMG_NULL)
+				continue;
+
+			PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle);
+
+		}
+
+		PVR_DPF((PVR_DBG_ERROR, "SGXDevInitPart2BW: A dissociate failed"));
+
+		psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+
+		/* A dissociation failure is unexpected */
+		PVR_DBG_BREAK;
+		return 0;
+	}
+
+	psSGXDevInitPart2OUT->eError =
+		DevInitSGXPart2KM(psPerProc,
+						  hDevCookieInt,
+						  &psSGXDevInitPart2IN->sInitInfo);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN,
+							 PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+//	PVRSRV_SGXDEV_INFO *psDevInfo;
+	IMG_HANDLE hHWRenderContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1);
+
+	psSGXRegHWRenderContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXRegHWRenderContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	hHWRenderContextInt =
+		SGXRegisterHWRenderContextKM(hDevCookieInt,
+                                     psSGXRegHWRenderContextIN->pHWRenderContextCpuVAddr,
+                                     psSGXRegHWRenderContextIN->ui32HWRenderContextSize,
+                                     psSGXRegHWRenderContextIN->ui32OffsetToPDDevPAddr,
+                                     psSGXRegHWRenderContextIN->hDevMemContext,
+                                     &psSGXRegHWRenderContextOUT->sHWRenderContextDevVAddr,
+                                     psPerProc);
+
+	if (hHWRenderContextInt == IMG_NULL)
+	{
+		psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXRegHWRenderContextOUT->hHWRenderContext,
+					  hHWRenderContextInt,
+					  PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hHWRenderContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hHWRenderContextInt,
+						   psSGXUnregHWRenderContextIN->hHWRenderContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt,
+													  psSGXUnregHWRenderContextIN->bForceCleanup);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psSGXUnregHWRenderContextIN->hHWRenderContext,
+							PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN,
+							 PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hHWTransferContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1);
+
+	psSGXRegHWTransferContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXRegHWTransferContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	hHWTransferContextInt =
+		SGXRegisterHWTransferContextKM(hDevCookieInt,
+									   psSGXRegHWTransferContextIN->pHWTransferContextCpuVAddr,
+                                       psSGXRegHWTransferContextIN->ui32HWTransferContextSize,
+                                       psSGXRegHWTransferContextIN->ui32OffsetToPDDevPAddr,
+                                       psSGXRegHWTransferContextIN->hDevMemContext,
+                                       &psSGXRegHWTransferContextOUT->sHWTransferContextDevVAddr,
+									   psPerProc);
+
+	if (hHWTransferContextInt == IMG_NULL)
+	{
+		psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXRegHWTransferContextOUT->hHWTransferContext,
+					  hHWTransferContextInt,
+					  PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hHWTransferContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hHWTransferContextInt,
+						   psSGXUnregHWTransferContextIN->hHWTransferContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt,
+														psSGXUnregHWTransferContextIN->bForceCleanup);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psSGXUnregHWTransferContextIN->hHWTransferContext,
+							PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+	return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXRegisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+							 PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN,
+							 PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT,
+							 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_HANDLE hHW2DContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1);
+
+	psSGXRegHW2DContextOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXRegHW2DContextIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	hHW2DContextInt =
+		SGXRegisterHW2DContextKM(hDevCookieInt,
+								 (IMG_CPU_VIRTADDR*)psSGXRegHW2DContextIN->hHW2DContextCpuVAddr,
+                                 psSGXRegHW2DContextIN->ui32HW2DContextSize,
+                                 psSGXRegHW2DContextIN->ui32OffsetToPDDevPAddr,
+								 psSGXRegHW2DContextIN->hDevMemContext,
+                                 &psSGXRegHW2DContextOUT->sHW2DContextDevVAddr,
+								 psPerProc);
+
+	if (hHW2DContextInt == IMG_NULL)
+	{
+		psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+		return 0;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXRegHW2DContextOUT->hHW2DContext,
+					  hHW2DContextInt,
+					  PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+							   PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN,
+							   PVRSRV_BRIDGE_RETURN *psRetOUT,
+							   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hHW2DContextInt;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hHW2DContextInt,
+						   psSGXUnregHW2DContextIN->hHW2DContext,
+						   PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt,
+												  psSGXUnregHW2DContextIN->bForceCleanup);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+							psSGXUnregHW2DContextIN->hHW2DContext,
+							PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+
+	return 0;
+}
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
+
+static IMG_INT
+SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+//	PVRSRV_SGXDEV_INFO *psDevInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXFlushHWRenderTargetIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+//	psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+	psRetOUT->eError = SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr, IMG_FALSE);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGX2DQueryBlitsCompleteBW(IMG_UINT32 ui32BridgeID,
+						  PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+						  PVRSRV_BRIDGE_RETURN *psRetOUT,
+						  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_VOID *pvSyncInfo;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   ps2DQueryBltsCompleteIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &pvSyncInfo,
+						   ps2DQueryBltsCompleteIN->hKernSyncInfo,
+						   PVRSRV_HANDLE_TYPE_SYNC_INFO);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+	psRetOUT->eError =
+		SGX2DQueryBlitsCompleteKM(psDevInfo,
+								  (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+								  ps2DQueryBltsCompleteIN->bWaitForComplete);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+					  PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+					  PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+					  PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL;
+	IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount = 0;
+	IMG_UINT32 i;
+	IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4);
+
+	psSGXFindSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+	psSGXFindSharedPBDescOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hDevCookieInt,
+						   psSGXFindSharedPBDescIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+		goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+	psSGXFindSharedPBDescOUT->eError =
+		SGXFindSharedPBDescKM(psPerProc, hDevCookieInt,
+							  psSGXFindSharedPBDescIN->bLockOnFailure,
+							  psSGXFindSharedPBDescIN->ui32TotalPBSize,
+							  &hSharedPBDesc,
+							  &psSharedPBDescKernelMemInfo,
+							  &psHWPBDescKernelMemInfo,
+							  &psBlockKernelMemInfo,
+							  &psHWBlockKernelMemInfo,
+							  &ppsSharedPBDescSubKernelMemInfos,
+							  &ui32SharedPBDescSubKernelMemInfosCount);
+	if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+		goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+	PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount
+			   <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+	psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount =
+		ui32SharedPBDescSubKernelMemInfosCount;
+
+	if(hSharedPBDesc == IMG_NULL)
+	{
+		psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
+		/* It's not an error if we don't find a buffer,
+		 * we just return NULL */
+		goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+					  &psSGXFindSharedPBDescOUT->hSharedPBDesc,
+					  hSharedPBDesc,
+					  PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+					  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+	/*
+	 * We allocate handles of type PVRSRV_HANDLE_TYPE_MEM_INFO_REF here,
+	 * as the process doesn't own the underlying memory, and so should
+	 * only be allowed a restricted set of operations on it, such as
+	 * mapping it into its address space.
+	 */
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
+					  psSharedPBDescKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+					  &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle,
+					  psHWPBDescKernelMemInfo,
+					  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+					  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+					  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+				  &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle,
+				  psBlockKernelMemInfo,
+				  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+				  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+				  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+	PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+				  &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle,
+				  psHWBlockKernelMemInfo,
+				  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+				  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+				  psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+
+	for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+	{
+		PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut =
+			psSGXFindSharedPBDescOUT;
+
+			PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+							  &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i],
+							  ppsSharedPBDescSubKernelMemInfos[i],
+							  PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+							  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+							  psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle);
+	}
+
+PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT:
+	if (ppsSharedPBDescSubKernelMemInfos != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+				  ppsSharedPBDescSubKernelMemInfos,
+				  IMG_NULL);
+	}
+
+	if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+	{
+		if(hSharedPBDesc != IMG_NULL)
+		{
+			SGXUnrefSharedPBDescKM(hSharedPBDesc);
+		}
+	}
+	else
+	{
+		COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc);
+	}
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXUnrefSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+					   PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hSharedPBDesc;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC);
+
+	psSGXUnrefSharedPBDescOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   &hSharedPBDesc,
+						   psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+						   PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+	if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXUnrefSharedPBDescOUT->eError =
+		SGXUnrefSharedPBDescKM(hSharedPBDesc);
+
+	if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXUnrefSharedPBDescOUT->eError =
+		PVRSRVReleaseHandle(psPerProc->psHandleBase,
+						   psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+						   PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+
+	return 0;
+}
+
+
+static IMG_INT
+SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+					 PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+					 PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+					 PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+	IMG_UINT32 ui32KernelMemInfoHandlesCount =
+		psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+	IMG_INT ret = 0;
+	IMG_HANDLE *phKernelMemInfoHandles = IMG_NULL;
+	PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = IMG_NULL;
+	IMG_UINT32 i;
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1);
+
+	psSGXAddSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+	PVR_ASSERT(ui32KernelMemInfoHandlesCount
+			   <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								&hDevCookieInt,
+								psSGXAddSharedPBDescIN->hDevCookie,
+								PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psSharedPBDescKernelMemInfo,
+								psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psHWPBDescKernelMemInfo,
+								psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psBlockKernelMemInfo,
+								psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+								(IMG_VOID **)&psHWBlockKernelMemInfo,
+								psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if(eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+
+	if(!OSAccessOK(PVR_VERIFY_READ,
+				   psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+				   ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+				 " Invalid phKernelMemInfos pointer", __FUNCTION__));
+		ret = -EFAULT;
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+				  (IMG_VOID **)&phKernelMemInfoHandles,
+				  0,
+				  "Array of Handles");
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			               ui32BridgeID,
+			               phKernelMemInfoHandles,
+						   psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+						   ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE))
+	   != PVRSRV_OK)
+	{
+		ret = -EFAULT;
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+				  (IMG_VOID **)&ppsKernelMemInfos,
+				  0,
+				  "Array of pointers to Kernel Memory Info");
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+	{
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+									(IMG_VOID **)&ppsKernelMemInfos[i],
+									phKernelMemInfoHandles[i],
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+		if(eError != PVRSRV_OK)
+		{
+			goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+		}
+	}
+
+	/*
+	 * Release all the handles we've just looked up, as none
+	 * of the associated resources will be valid for access via
+	 * those handles once we return from SGXAddSharedPBDesc.
+	 */
+	/* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	/* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
+	eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+								psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+								PVRSRV_HANDLE_TYPE_MEM_INFO);
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+	{
+		/* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
+		eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+									phKernelMemInfoHandles[i],
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+		PVR_ASSERT(eError == PVRSRV_OK);
+	}
+
+	eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt,
+								  psSharedPBDescKernelMemInfo,
+								  psHWPBDescKernelMemInfo,
+								  psBlockKernelMemInfo,
+								  psHWBlockKernelMemInfo,
+								  psSGXAddSharedPBDescIN->ui32TotalPBSize,
+								  &hSharedPBDesc,
+								  ppsKernelMemInfos,
+								  ui32KernelMemInfoHandlesCount,
+								  psSGXAddSharedPBDescIN->sHWPBDescDevVAddr);
+
+
+	if (eError != PVRSRV_OK)
+	{
+		goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+	}
+
+	PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+				  &psSGXAddSharedPBDescOUT->hSharedPBDesc,
+				  hSharedPBDesc,
+				  PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+				  PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT:
+
+	if(phKernelMemInfoHandles)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+				  (IMG_VOID *)phKernelMemInfoHandles,
+				  0);
+	}
+	if(ppsKernelMemInfos)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+				  (IMG_VOID *)ppsKernelMemInfos,
+				  0);
+	}
+
+	if(ret == 0 && eError == PVRSRV_OK)
+	{
+		COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc);
+	}
+
+	psSGXAddSharedPBDescOUT->eError = eError;
+
+	return ret;
+}
+
+static IMG_INT
+SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
+					   PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+					   PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+					   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_HANDLE hDevCookieInt;
+	IMG_UINT32 i;
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT);
+
+	NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+	if(!psPerProc->bInitProcess)
+	{
+		psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+		return 0;
+	}
+
+	psSGXInfoForSrvinitOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+						   psSGXInfoForSrvinitIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+	if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psSGXInfoForSrvinitOUT->eError =
+		SGXGetInfoForSrvinitKM(hDevCookieInt,
+							   &psSGXInfoForSrvinitOUT->sInitInfo);
+
+	if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		PVRSRV_HEAP_INFO *psHeapInfo;
+
+		psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i];
+
+		if (psHeapInfo->ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID)
+		{
+			IMG_HANDLE hDevMemHeapExt;
+
+			if (psHeapInfo->hDevMemHeap != IMG_NULL)
+			{
+				/* Allocate heap handle */
+				PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+								  &hDevMemHeapExt,
+								  psHeapInfo->hDevMemHeap,
+								  PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+								  PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+				psHeapInfo->hDevMemHeap = hDevMemHeapExt;
+			}
+		}
+	}
+
+	COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc);
+
+	return 0;
+}
+
+#if defined(PDUMP)
+// PRQA S 5120++
+/*****************************************************************************
+ FUNCTION	: DumpBufferArray
+ PURPOSE	: PDUMP information in stored buffer array
+ PARAMETERS	:
+ RETURNS	:
+*****************************************************************************/
+static IMG_VOID
+DumpBufferArray(PVRSRV_PER_PROCESS_DATA   *psPerProc,
+				PSGX_KICKTA_DUMP_BUFFER	psBufferArray,
+				IMG_UINT32                 ui32BufferArrayLength,
+				IMG_BOOL                   bDumpPolls)
+{
+	IMG_UINT32	i;
+
+	for (i=0; i<ui32BufferArrayLength; i++)
+	{
+		PSGX_KICKTA_DUMP_BUFFER	psBuffer;
+		PVRSRV_KERNEL_MEM_INFO    *psCtrlMemInfoKM;
+		IMG_CHAR * pszName;
+		IMG_HANDLE hUniqueTag;
+		IMG_UINT32	ui32Offset;
+
+		psBuffer = &psBufferArray[i];
+		pszName = (IMG_CHAR *)psBuffer->hName;
+		if (!pszName)
+		{
+			pszName = "Nameless buffer";
+		}
+
+		hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo);
+
+	#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+		psCtrlMemInfoKM	= ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo);
+		ui32Offset =  psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr;
+	#else
+		psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+		ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+	#endif
+
+		if (psBuffer->ui32Start <= psBuffer->ui32End)
+		{
+			if (bDumpPolls)
+			{
+				PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+				PDUMPCBP(psCtrlMemInfoKM,
+						 ui32Offset,
+						 psBuffer->ui32Start,
+						 psBuffer->ui32SpaceUsed,
+						 psBuffer->ui32BufferSize,
+						 0,
+						 MAKEUNIQUETAG(psCtrlMemInfoKM));
+			}
+
+			PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+			PDUMPMEMUM(psPerProc,
+					 IMG_NULL,
+					 psBuffer->hLinAddr,
+					 (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+					 psBuffer->ui32Start,
+					 psBuffer->ui32End - psBuffer->ui32Start,
+					 0,
+					 hUniqueTag);
+		}
+		else
+		{
+			/*
+				Range of data wraps the end of the buffer so it needs to be dumped in two sections
+			*/
+
+			if (bDumpPolls)
+			{
+				PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+				PDUMPCBP(psCtrlMemInfoKM,
+						 ui32Offset,
+						 psBuffer->ui32Start,
+						 psBuffer->ui32BackEndLength,
+						 psBuffer->ui32BufferSize,
+						 0,
+						 MAKEUNIQUETAG(psCtrlMemInfoKM));
+			}
+			PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+			PDUMPMEMUM(psPerProc,
+					 IMG_NULL,
+					 psBuffer->hLinAddr,
+					 (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+					 psBuffer->ui32Start,
+					 psBuffer->ui32BackEndLength,
+					 0,
+					 hUniqueTag);
+
+			if (bDumpPolls)
+			{
+				PDUMPMEMPOL(psCtrlMemInfoKM,
+							ui32Offset,
+							0,
+							0xFFFFFFFF,
+							PDUMP_POLL_OPERATOR_NOTEQUAL,
+							0,
+							MAKEUNIQUETAG(psCtrlMemInfoKM));
+
+				PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+				PDUMPCBP(psCtrlMemInfoKM,
+						 ui32Offset,
+						 0,
+						 psBuffer->ui32End,
+						 psBuffer->ui32BufferSize,
+						 0,
+						 MAKEUNIQUETAG(psCtrlMemInfoKM));
+			}
+			PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+			PDUMPMEMUM(psPerProc,
+					 IMG_NULL,
+					 psBuffer->hLinAddr,
+					 (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+					 0,
+					 psBuffer->ui32End,
+					 0,
+					 hUniqueTag);
+		}
+	}
+}
+static IMG_INT
+SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+				   IMG_VOID *psBridgeOut,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 i;
+#if defined(__QNXNTO__)
+    const IMG_UINT32 NAME_BUFFER_SIZE = 30;
+    IMG_PCHAR pszNameBuffer, pszName;
+    IMG_UINT32 ui32NameBufferArraySize, ui32NameLength;
+#endif
+	SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+	IMG_UINT32 ui32BufferArrayLength =
+		psPDumpBufferArrayIN->ui32BufferArrayLength;
+	IMG_UINT32 ui32BufferArraySize =
+		ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
+	PVRSRV_ERROR eError = PVRSRV_ERROR_TOO_FEW_BUFFERS;
+
+	PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32BufferArraySize,
+				  (IMG_PVOID *)&psKickTADumpBuffer, 0,
+				  "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+	{
+		return -ENOMEM;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			               ui32BridgeID,
+						   psKickTADumpBuffer,
+						   psPDumpBufferArrayIN->hBufferArray,
+						   ui32BufferArraySize) != PVRSRV_OK)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+		/*not nulling pointer, out of scope*/
+		return -EFAULT;
+	}
+
+#if defined (__QNXNTO__)
+    ui32NameBufferArraySize = ui32BufferArrayLength * NAME_BUFFER_SIZE;
+    if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize,
+            (IMG_PVOID *)&pszNameBuffer, 0,
+            "Kick Tile Accelerator Dump Buffer names") != PVRSRV_OK)
+    {
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+        return -ENOMEM;
+    }
+
+    pszName = pszNameBuffer;
+
+	for(i = 0; i < ui32BufferArrayLength; i++)
+	{
+        if (psKickTADumpBuffer[i].hName)
+        {
+            ui32NameLength = psKickTADumpBuffer[i].ui32NameLength;
+            if (ui32NameLength >= NAME_BUFFER_SIZE)
+            {
+                ui32NameLength = NAME_BUFFER_SIZE - 1;
+            }
+
+            if (ui32NameLength && 
+                (CopyFromUserWrapper(psPerProc, ui32BridgeID, pszName, 
+                    psKickTADumpBuffer[i].hName, ui32NameLength + 1) == PVRSRV_OK))
+            {
+                pszName[NAME_BUFFER_SIZE - 1] = 0;
+                psKickTADumpBuffer[i].hName = (IMG_HANDLE)pszName;
+                pszName += NAME_BUFFER_SIZE;
+            }
+            else 
+            {
+                PVR_DPF((PVR_DBG_WARNING, "Failed to read PDUMP buffer name"));
+                psKickTADumpBuffer[i].hName = 0;
+            }
+        }
+    }
+#endif
+
+	for(i = 0; i < ui32BufferArrayLength; i++)
+	{
+		IMG_VOID *pvMemInfo;
+
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+									&pvMemInfo,
+									psKickTADumpBuffer[i].hKernelMemInfo,
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+					 "PVRSRVLookupHandle failed (%d)", eError));
+			break;
+		}
+		psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+		eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+									&pvMemInfo,
+									psKickTADumpBuffer[i].hCtrlKernelMemInfo,
+									PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+					 "PVRSRVLookupHandle failed (%d)", eError));
+			break;
+		}
+		psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo;
+#endif
+
+	}
+
+	if(eError == PVRSRV_OK)
+	{
+		DumpBufferArray(psPerProc,
+						psKickTADumpBuffer,
+						ui32BufferArrayLength,
+						psPDumpBufferArrayIN->bDumpPolls);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+#if defined (__QNXNTO__)
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize, pszNameBuffer, 0);
+#endif
+	/*not nulling pointer, out of scope*/
+
+	return 0;
+}
+
+static IMG_INT
+SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN,
+				   PVRSRV_BRIDGE_RETURN *psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32RegisterArraySize =  psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+	IMG_UINT32 *pui32Registers = IMG_NULL;
+	PVRSRV_SGXDEV_INFO	*psDevInfo;
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	IMG_UINT32	ui32RegVal = 0;
+#endif
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_HANDLE hDevMemContextInt = 0;
+	IMG_UINT32 ui32MMUContextID;
+	IMG_INT ret = -EFAULT;
+
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+	if (ui32RegisterArraySize == 0)
+	{
+		goto ExitNoError;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID**)&psDeviceNode,
+						   psPDump3DSignatureRegistersIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+		goto Exit;
+	}
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	/* Enable all cores available */
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+						psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32RegisterArraySize,
+				  (IMG_PVOID *)&pui32Registers, 0,
+				  "Array of Registers") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed"));
+		goto Exit;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			        	ui32BridgeID,
+					pui32Registers,
+					psPDump3DSignatureRegistersIN->hRegisters,
+					ui32RegisterArraySize) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed"));
+		goto Exit;
+	}
+
+	PDump3DSignatureRegisters(&psDeviceNode->sDevId,
+					psPDump3DSignatureRegistersIN->ui32DumpFrameNum,
+					psPDump3DSignatureRegistersIN->bLastFrame,
+					pui32Registers,
+					psPDump3DSignatureRegistersIN->ui32NumRegisters);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(	psPerProc->psHandleBase,
+							&hDevMemContextInt,
+							psPDump3DSignatureRegistersIN->hDevMemContext,
+							PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* look up the MMU context ID */
+	PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
+	ui32MMUContextID = psDeviceNode->pfnMMUGetContextID((IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext);
+
+	PDumpSignatureBuffer(&psDeviceNode->sDevId,
+						 "out.tasig", "TA", 0,
+						 psDevInfo->psKernelTASigBufferMemInfo->sDevVAddr,
+						 (IMG_UINT32)psDevInfo->psKernelTASigBufferMemInfo->uAllocSize,
+						 ui32MMUContextID,
+						 0 /*ui32PDumpFlags*/);
+	PDumpSignatureBuffer(&psDeviceNode->sDevId,
+						 "out.3dsig", "3D", 0,
+						 psDevInfo->psKernel3DSigBufferMemInfo->sDevVAddr,
+						 (IMG_UINT32)psDevInfo->psKernel3DSigBufferMemInfo->uAllocSize,
+						 ui32MMUContextID,
+						 0 /*ui32PDumpFlags*/);
+
+ExitNoError:
+	psRetOUT->eError = PVRSRV_OK;
+	ret = 0;
+Exit:
+	if (pui32Registers != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+	}
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	if (psDevInfo != IMG_NULL)
+	{
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+							psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+	}
+#endif
+
+	return ret;
+}
+
+static IMG_INT
+SGXPDumpCounterRegistersBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN,
+				   IMG_VOID *psBridgeOut,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32RegisterArraySize =  psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+	IMG_UINT32 *pui32Registers = IMG_NULL;
+	PVRSRV_DEVICE_NODE *psDeviceNode ;
+	IMG_INT ret = -EFAULT;
+
+	PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS);
+
+	if (ui32RegisterArraySize == 0)
+	{
+		goto ExitNoError;
+	}
+
+	if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+						  (IMG_VOID**)&psDeviceNode,
+						  psPDumpCounterRegistersIN->hDevCookie,
+						  PVRSRV_HANDLE_TYPE_DEV_NODE) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXPDumpCounterRegistersBW: hDevCookie lookup failed"));
+		ret = -ENOMEM;
+		goto Exit;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32RegisterArraySize,
+				  (IMG_PVOID *)&pui32Registers, 0,
+				  "Array of Registers") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed"));
+		ret = -ENOMEM;
+		goto Exit;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			        	ui32BridgeID,
+					pui32Registers,
+					psPDumpCounterRegistersIN->hRegisters,
+					ui32RegisterArraySize) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed"));
+		goto Exit;
+	}
+
+	PDumpCounterRegisters(&psDeviceNode->sDevId,
+					psPDumpCounterRegistersIN->ui32DumpFrameNum,
+					psPDumpCounterRegistersIN->bLastFrame,
+					pui32Registers,
+					psPDumpCounterRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+	ret = 0;
+Exit:
+	if (pui32Registers != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+	}
+
+	return ret;
+}
+
+static IMG_INT
+SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN,
+				   PVRSRV_BRIDGE_RETURN *psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	IMG_UINT32 ui32RegisterArraySize =  psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+	IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	PVRSRV_SGXDEV_INFO	*psDevInfo = IMG_NULL;
+	IMG_UINT32	ui32RegVal = 0;
+#endif
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_INT ret = -EFAULT;
+
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+	if (ui32RegisterArraySize == 0)
+	{
+		goto ExitNoError;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+						   psPDumpTASignatureRegistersIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+		goto Exit;
+	}
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+	/* Enable all cores available */
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+						psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  ui32RegisterArraySize,
+				  (IMG_PVOID *)&pui32Registers, 0,
+				  "Array of Registers") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed"));
+		ret = -ENOMEM;
+		goto Exit;
+	}
+
+	if(CopyFromUserWrapper(psPerProc,
+			        	ui32BridgeID,
+					pui32Registers,
+					psPDumpTASignatureRegistersIN->hRegisters,
+					ui32RegisterArraySize) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed"));
+		goto Exit;
+	}
+
+	PDumpTASignatureRegisters(&psDeviceNode->sDevId,
+					psPDumpTASignatureRegistersIN->ui32DumpFrameNum,
+					psPDumpTASignatureRegistersIN->ui32TAKickCount,
+					psPDumpTASignatureRegistersIN->bLastFrame,
+					pui32Registers,
+					psPDumpTASignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+	psRetOUT->eError = PVRSRV_OK;
+	ret = 0;
+Exit:
+	if (pui32Registers != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+	}
+
+#if defined(SGX_FEATURE_MP)	&& defined(FIX_HW_BRN_27270)
+	if (psDevInfo != IMG_NULL)
+	{
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+							psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+	}
+#endif
+
+	return ret;
+}
+//PRQA S 5120--
+
+
+static IMG_INT
+SGXPDumpHWPerfCBBW(IMG_UINT32						ui32BridgeID,
+				   PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB	*psPDumpHWPerfCBIN,
+				   PVRSRV_BRIDGE_RETURN 			*psRetOUT,
+				   PVRSRV_PER_PROCESS_DATA 			*psPerProc)
+{
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined(__linux__) || defined(__QNXNTO__)
+	PVRSRV_SGXDEV_INFO	*psDevInfo;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_HANDLE hDevMemContextInt = 0;
+	IMG_UINT32 ui32MMUContextID = 0;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+						   psPDumpHWPerfCBIN->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(	psPerProc->psHandleBase,
+							&hDevMemContextInt,
+							psPDumpHWPerfCBIN->hDevMemContext,
+							PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* look up the MMU context ID */
+	PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
+	ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
+
+	PDumpHWPerfCBKM(&psDeviceNode->sDevId,
+					&psPDumpHWPerfCBIN->szFileName[0],
+					psPDumpHWPerfCBIN->ui32FileOffset,
+					psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+					psDevInfo->psKernelHWPerfCBMemInfo->uAllocSize,
+					ui32MMUContextID,
+					psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+	return 0;
+#else
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+	PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	return 0;
+#endif
+#else
+	PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+	PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+	PVR_UNREFERENCED_PARAMETER(psRetOUT);
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	return -EFAULT;
+#endif /* defined(SUPPORT_SGX_HWPERF) */
+}
+
+
+static IMG_INT
+SGXPDumpSaveMemBW(IMG_UINT32						ui32BridgeID,
+				  PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM	*psPDumpSaveMem,
+				  PVRSRV_BRIDGE_RETURN 				*psRetOUT,
+				  PVRSRV_PER_PROCESS_DATA 			*psPerProc)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_HANDLE hDevMemContextInt = 0;
+	IMG_UINT32 ui32MMUContextID;
+
+	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM);
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(psPerProc->psHandleBase,
+						   (IMG_VOID**)&psDeviceNode,
+						   psPDumpSaveMem->hDevCookie,
+						   PVRSRV_HANDLE_TYPE_DEV_NODE);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	psRetOUT->eError =
+		PVRSRVLookupHandle(	psPerProc->psHandleBase,
+							&hDevMemContextInt,
+							psPDumpSaveMem->hDevMemContext,
+							PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+	if(psRetOUT->eError != PVRSRV_OK)
+	{
+		return 0;
+	}
+
+	/* look up the MMU context ID */
+	PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
+	ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
+
+	PDumpSaveMemKM(&psDeviceNode->sDevId,
+				   &psPDumpSaveMem->szFileName[0],
+				   psPDumpSaveMem->ui32FileOffset,
+				   psPDumpSaveMem->sDevVAddr,
+				   psPDumpSaveMem->ui32Size,
+				   ui32MMUContextID,
+				   psPDumpSaveMem->ui32PDumpFlags);
+	return 0;
+}
+
+#endif /* PDUMP */
+
+
+/* PRQA S 0313,3635 END_SET_SGX */ /* function macro required this format */
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
+{
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETCLIENTINFO, SGXGetClientInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DOKICK, SGXDoKickBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR, DummyBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READREGISTRYDWORD, DummyBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW);
+
+#if defined(TRANSFER_QUEUE)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER, SGXSubmitTransferBW);
+#endif
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMISCINFO, SGXGetMiscInfoBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT	, SGXGetInfoForSrvinitBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DEVINITPART2, SGXDevInitPart2BW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMIT2D, SGXSubmit2DBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW);
+#endif
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW);
+
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW);
+    SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SET_RENDER_CONTEXT_PRIORITY, SGXSetRenderContextPriorityBW);
+    SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SET_TRANSFER_CONTEXT_PRIORITY, SGXSetTransferContextPriorityBW);
+
+#if defined(PDUMP)
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW);
+	SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM, SGXPDumpSaveMemBW);
+#endif
+}
+/* PRQA L:END_SET_SGX */ /* end of setup overrides */
+
+#endif /* SUPPORT_SGX */
diff --git a/drivers/gpu/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h b/drivers/gpu/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
new file mode 100644
index 0000000..3cb6282
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
@@ -0,0 +1,61 @@
+/*************************************************************************/ /*!
+@Title          SGX Bridge Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the PVR Bridge code
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __BRIDGED_SGX_BRIDGE_H__
+#define __BRIDGED_SGX_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __BRIDGED_SGX_BRIDGE_H__ */
+
+/******************************************************************************
+ End of file (bridged_sgx_bridge.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/buffer_manager.c b/drivers/gpu/pvr/services4/srvkm/common/buffer_manager.c
new file mode 100644
index 0000000..bd21023
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/buffer_manager.c
@@ -0,0 +1,3485 @@
+/*************************************************************************/ /*!
+@Title          Buffer management functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Manages buffers mapped into two memory spaces - cpu and device,
+                either of which can be virtual or physical.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+
+#include "sysconfig.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "lists.h"
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags);
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
+static IMG_BOOL
+BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
+				IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+				IMG_UINT32 ui32Flags, IMG_PVOID pvPrivData,
+				IMG_UINT32 ui32PrivDataLength, IMG_UINTPTR_T *pBase);
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+				BM_MAPPING *pMapping,
+				IMG_SIZE_T *pActualSize,
+				IMG_UINT32 ui32Flags,
+				IMG_UINT32 dev_vaddr_alignment,
+				IMG_DEV_VIRTADDR *pDevVAddr);
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping);
+
+/*!
+******************************************************************************
+
+	@Function   AllocMemory
+
+	@Description	Allocate a buffer mapped into both cpu and device virtual
+				address spaces.  This is now quite simple:
+
+				1. Choose whence to get the memory;
+				2. Obtain memory from that source;
+				3. Work out the actual buffer addresses in other spaces.
+
+				In choosing whence to get the memory we work like this:
+
+				1. If an import arena exists, use unless BP_CONTIGUOUS is set;
+				2. Use a contiguous pool.
+
+	@Input      pBMContext - BM context
+	@Input      psBMHeap - BM heap
+	@Input      psDevVAddr - device virtual address (optional)
+	@Input      uSize - requested buffer size in bytes.
+	@Input      ui32Flags - property flags for the buffer.
+    @Input      uDevVAddrAlignment - required device virtual address
+					 alignment, or 0.
+    @Input      pvPrivData - opaque private data passed through to allocator
+    @Input      ui32PrivDataLength - length of opaque private data
+
+	@Output		pui32TimeToDevMap - Time taken  in us to map the allocated
+					buffer to device MMU. 
+	@Output     pBuf - receives a pointer to a descriptor of the allocated
+					 buffer.
+	@Return 	IMG_TRUE - Success
+				IMG_FALSE - Failed.
+
+ *****************************************************************************/
+static IMG_BOOL
+AllocMemory (BM_CONTEXT			*pBMContext,
+			 BM_HEAP			*psBMHeap,
+			 IMG_DEV_VIRTADDR	*psDevVAddr,
+			 IMG_SIZE_T			uSize,
+			 IMG_UINT32			ui32Flags,
+			 IMG_UINT32			uDevVAddrAlignment,
+			 IMG_PVOID			pvPrivData,
+			 IMG_UINT32			ui32PrivDataLength,
+			 IMG_UINT32			ui32ChunkSize,
+			 IMG_UINT32			ui32NumVirtChunks,
+			 IMG_UINT32			ui32NumPhysChunks,
+			 IMG_BOOL			*pabMapChunk,
+			 #if defined (PVRSRV_DEVMEM_TIME_STATS)
+			 IMG_UINT32			*pui32TimeToDevMap,
+			 #endif
+			 BM_BUF				*pBuf)
+{
+	BM_MAPPING			*pMapping;
+	IMG_UINTPTR_T		uOffset;
+	RA_ARENA			*pArena = IMG_NULL;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "AllocMemory (uSize=0x%" SIZE_T_FMT_LEN "x, ui32Flags=0x%x, align=0x%x)",
+			  uSize, ui32Flags, uDevVAddrAlignment));
+
+	/*
+		Decision depends on combination of DevVaddr generation
+		and backing RAM requirement
+	*/
+	if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+	{
+		if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+		{
+			/* user supplied DevVAddr, RAM backing */
+			PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
+			return IMG_FALSE;
+		}
+
+		/* BM supplied DevVAddr, RAM Backing */
+
+		/* check heap attributes */
+		if(psBMHeap->ui32Attribs
+		   &	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+		   |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+		{
+			/* specify arena (VM+RAM)*/
+			pArena = psBMHeap->pImportArena;
+			PVR_ASSERT(psBMHeap->sDevArena.psDeviceMemoryHeapInfo->ui32Attribs & PVRSRV_MEM_RAM_BACKED_ALLOCATION);
+		}
+		else
+		{
+			PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: backing store type doesn't match heap"));
+			return IMG_FALSE;
+		}
+
+		/* Now allocate from the arena we chose above. */
+		if (ui32Flags & PVRSRV_MEM_SPARSE)
+		{
+			IMG_BOOL bSuccess;
+			IMG_SIZE_T uActualSize;
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+			IMG_UINT64 ui64TimeStart;
+#endif
+
+			/* Allocate physical memory */
+			bSuccess = BM_ImportMemory(psBMHeap,
+									   ui32ChunkSize * ui32NumPhysChunks,
+									   &uActualSize,
+									   &pMapping,
+									   ui32Flags,
+									   pvPrivData,
+									   ui32PrivDataLength,
+									   IMG_NULL);	/* We allocate VM space */
+
+			if (!bSuccess)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: BM_ImportMemory failed"));
+				return IMG_FALSE;
+			}
+
+			if (uActualSize != ui32ChunkSize * ui32NumPhysChunks)
+			{
+				/*
+					Most likely the chunksize was not host page multiple so
+					return with an error
+				*/
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: Failed to allocate memory for sparse allocation"));
+				BM_FreeMemory(pArena, IMG_NULL, pMapping);
+				return IMG_FALSE;
+			}
+
+			pMapping->uSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+			uSize = pMapping->uSizeVM;
+			pMapping->ui32ChunkSize = ui32ChunkSize;
+			pMapping->ui32NumVirtChunks = ui32NumVirtChunks;
+			pMapping->ui32NumPhysChunks = ui32NumPhysChunks;
+			pMapping->pabMapChunk = pabMapChunk;
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+			ui64TimeStart = OSClockMonotonicus();
+#endif
+			/* Allocate VA space and map in the physical memory */
+			bSuccess = DevMemoryAlloc (pBMContext,
+										pMapping,
+										IMG_NULL,
+										ui32Flags,
+										uDevVAddrAlignment,
+										&pMapping->DevVAddr);
+			if (!bSuccess)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						"AllocMemory: Failed to allocate device memory"));
+				BM_FreeMemory(pArena, IMG_NULL, pMapping);
+				return IMG_FALSE;
+			}
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+			pMapping->ui32TimeToDevMap = OSClockMonotonicus() - ui64TimeStart;
+#endif
+			/* uDevVAddrAlignment is currently set to zero so QAC generates warning which we override */
+			/* PRQA S 3356,3358 1 */
+			PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+			pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr;
+		}
+		else
+		{
+			if (!RA_Alloc(pArena,
+						  uSize,
+						  IMG_NULL,
+						  (IMG_VOID*) &pMapping,
+						  ui32Flags,
+						  uDevVAddrAlignment,
+						  0,
+						  pvPrivData,
+						  ui32PrivDataLength,
+						  (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%" SIZE_T_FMT_LEN "x) FAILED", uSize));
+				return IMG_FALSE;
+			}
+		}
+
+		uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
+		if(pMapping->CpuVAddr)
+		{
+			pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
+		}
+		else
+		{
+			pBuf->CpuVAddr = IMG_NULL;
+		}
+
+		if(uSize == pMapping->uSizeVM)
+		{
+			pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+		}
+		else
+		{
+			if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+								 uOffset,
+								 uSize,
+								 psBMHeap->ui32Attribs,
+								 &pBuf->hOSMemHandle)!=PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSGetSubMemHandle FAILED"));
+				return IMG_FALSE;
+			}
+		}
+
+		/* for hm_contiguous and hm_wrapped memory, the pMapping
+		 * will have a physical address, else 0 */
+		pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+		if(ui32Flags & PVRSRV_MEM_ZERO)
+		{
+			if(!ZeroBuf(pBuf, pMapping, uSize, psBMHeap->ui32Attribs | ui32Flags))
+			{
+				return IMG_FALSE;
+			}
+		}
+	}
+	else
+	{
+		if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+		{
+			/* user supplied DevVAddr, no RAM backing */
+			PVR_ASSERT(psDevVAddr != IMG_NULL);
+
+			if (psDevVAddr == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr"));
+				return IMG_FALSE;
+			}
+
+			/* just make space in the pagetables */
+			pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+													uSize,
+													IMG_NULL,
+													PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+													uDevVAddrAlignment,
+													psDevVAddr);
+
+			/* setup buf */
+			pBuf->DevVAddr = *psDevVAddr;
+		}
+		else
+		{
+			IMG_BOOL bResult;
+			/* BM supplied DevVAddr, no RAM Backing */
+
+			/* just make space in the pagetables */
+			bResult = pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+													uSize,
+													IMG_NULL,
+													0,
+													uDevVAddrAlignment,
+													&pBuf->DevVAddr);
+
+			if(!bResult)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "AllocMemory: MMUAlloc failed"));
+				return IMG_FALSE;
+			}
+		}
+
+		/* allocate a mocked-up mapping */
+		if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+							sizeof (struct _BM_MAPPING_),
+							(IMG_PVOID *)&pMapping, IMG_NULL,
+							"Buffer Manager Mapping") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSAllocMem(0x%" SIZE_T_FMT_LEN "x) FAILED", sizeof(*pMapping)));
+			return IMG_FALSE;
+		}
+
+		/* setup buf */
+		pBuf->CpuVAddr = IMG_NULL;
+		pBuf->hOSMemHandle = 0;
+		pBuf->CpuPAddr.uiAddr = 0;
+
+		/* setup mapping */
+		pMapping->CpuVAddr = IMG_NULL;
+		pMapping->CpuPAddr.uiAddr = 0;
+		pMapping->DevVAddr = pBuf->DevVAddr;
+		pMapping->psSysAddr = IMG_NULL;
+		pMapping->uSize = uSize;
+		pMapping->hOSMemHandle = 0;
+	}
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	*pui32TimeToDevMap = pMapping->ui32TimeToDevMap;
+#endif
+
+	/* Record the arena pointer in the mapping. */
+	pMapping->pArena = pArena;
+
+	/* record the heap */
+	pMapping->pBMHeap = psBMHeap;
+	pBuf->pMapping = pMapping;
+
+	/* output some stats */
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"AllocMemory: pMapping=%p: DevV=%08X CpuV=%p CpuP=" CPUPADDR_FMT " uSize=0x%" SIZE_T_FMT_LEN "x",
+				pMapping,
+				pMapping->DevVAddr.uiAddr,
+				pMapping->CpuVAddr,
+				pMapping->CpuPAddr.uiAddr,
+				pMapping->uSize));
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"AllocMemory: pBuf=%p: DevV=%08X CpuV=%p CpuP=" CPUPADDR_FMT " uSize=0x%" SIZE_T_FMT_LEN "x",
+				pBuf,
+				pBuf->DevVAddr.uiAddr,
+				pBuf->CpuVAddr,
+				pBuf->CpuPAddr.uiAddr,
+				uSize));
+
+	/* Verify virtual device address alignment */
+	PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
+
+	return IMG_TRUE;
+}
+
+
+/*!
+******************************************************************************
+
+	@Function	WrapMemory
+
+	@Description Allocate a buffer mapped into both cpu and device virtual
+				address spaces.
+
+	@Input      psBMHeap - BM heap
+	@Input      uSize - requested buffer size in bytes.
+	@Input      ui32BaseOffset - Offset from page of wrap.
+	@Input      bPhysContig - Is the wrap physically contiguous.
+	@Input      psAddr - List of pages to wrap.
+	@Input      pvCPUVAddr - Optional CPU Kernel virtual address (page aligned) of memory to wrap
+	@Input      ui32Flags - property flags for the buffer.
+	@Output     Buf - receives a pointer to a descriptor of the allocated
+					 buffer.
+	@Return 	IMG_TRUE - Success
+				IMG_FALSE - Failed.
+
+ *****************************************************************************/
+static IMG_BOOL
+WrapMemory (BM_HEAP *psBMHeap,
+			IMG_SIZE_T uSize,
+			IMG_SIZE_T uiBaseOffset,
+			IMG_BOOL bPhysContig,
+			IMG_SYS_PHYADDR *psAddr,
+			IMG_VOID *pvCPUVAddr,
+			IMG_UINT32 ui32Flags,
+			BM_BUF *pBuf)
+{
+	IMG_DEV_VIRTADDR DevVAddr = {0};
+	BM_MAPPING *pMapping;
+	IMG_BOOL bResult;
+	IMG_SIZE_T const uPageSize = HOST_PAGESIZE();
+	/* We should not pass down R/W flags into the OS layers so create ui32Attribs */
+	IMG_UINT32 ui32Attribs = ui32Flags & ~(PVRSRV_MEM_READ | PVRSRV_MEM_WRITE);
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "WrapMemory(psBMHeap=%p, size=0x%" SIZE_T_FMT_LEN "x, offset=0x%" SIZE_T_FMT_LEN 
+			  "x, bPhysContig=0x%x, sysPAddr=0x" SYSPADDR_FMT ", pvCPUVAddr = 0x%p, flags=0x%x)",
+			  psBMHeap, 
+              uSize, 
+              uiBaseOffset, 
+              bPhysContig, 
+			  psAddr->uiAddr,
+              pvCPUVAddr, 
+              ui32Flags));
+
+	PVR_ASSERT((psAddr->uiAddr & (uPageSize - 1)) == 0);
+	/* Only need lower 12 bits of the cpu addr - don't care what size a void* is */
+	PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (uPageSize - 1)) == 0);
+
+	uSize += uiBaseOffset;
+	uSize = HOST_PAGEALIGN (uSize);
+
+	/* allocate a mocked-up mapping */
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(*pMapping),
+						(IMG_PVOID *)&pMapping, IMG_NULL,
+						"Mocked-up mapping") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%" SIZE_T_FMT_LEN "x) FAILED", sizeof(*pMapping)));
+		return IMG_FALSE;
+	}
+
+	OSMemSet(pMapping, 0, sizeof (*pMapping));
+
+	pMapping->uSize = uSize;
+	pMapping->uSizeVM = uSize;
+	pMapping->pBMHeap = psBMHeap;
+
+	if(pvCPUVAddr)
+	{
+		pMapping->CpuVAddr = pvCPUVAddr;
+
+		if (bPhysContig)
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
+			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+			if(OSRegisterMem(pMapping->CpuPAddr,
+							pMapping->CpuVAddr,
+							pMapping->uSize,
+							ui32Attribs,
+							&pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSRegisterMem Phys=0x" CPUPADDR_FMT ", Size=%" SIZE_T_FMT_LEN "u) failed",
+					pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+		else
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped_scatter_virtaddr;
+			pMapping->psSysAddr = psAddr;
+
+			if(OSRegisterDiscontigMem(pMapping->psSysAddr,
+							pMapping->CpuVAddr,
+							pMapping->uSize,
+							ui32Attribs,
+							&pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSRegisterDiscontigMem Size=0x%" SIZE_T_FMT_LEN "u) failed",
+					pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+	}
+	else
+	{
+		if (bPhysContig)
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped;
+			pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+			if(OSReservePhys(pMapping->CpuPAddr,
+							 pMapping->uSize,
+							 ui32Attribs,
+							 IMG_NULL,
+							 &pMapping->CpuVAddr,
+							 &pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSReservePhys Phys=0x" CPUPADDR_FMT ", Size=%" SIZE_T_FMT_LEN "u) failed",
+					pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+		else
+		{
+			pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
+			pMapping->psSysAddr = psAddr;
+
+			if(OSReserveDiscontigPhys(pMapping->psSysAddr,
+							 pMapping->uSize,
+							 ui32Attribs,
+							 &pMapping->CpuVAddr,
+							 &pMapping->hOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,	"WrapMemory: OSReserveDiscontigPhys Size=%" SIZE_T_FMT_LEN "u) failed",
+					pMapping->uSize));
+				goto fail_cleanup;
+			}
+		}
+	}
+
+	/*
+	 * Allocate device memory for this buffer.
+	 */
+	bResult = DevMemoryAlloc(psBMHeap->pBMContext,
+							 pMapping,
+							 IMG_NULL,
+							 ui32Flags,
+							 IMG_CAST_TO_DEVVADDR_UINT(uPageSize),
+							 &DevVAddr);
+	if (!bResult)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"WrapMemory: DevMemoryAlloc(0x%" SIZE_T_FMT_LEN "x) failed",
+				pMapping->uSize));
+		goto fail_cleanup;
+	}
+
+	/*
+	 * Determine the offset of this allocation within the underlying
+	 * dual mapped chunk of memory, we can assume that all three
+	 * addresses associated with this allocation are placed at the same
+	 * offset within the underlying chunk.
+	 */
+	pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uiBaseOffset;
+	if(!uiBaseOffset)
+	{
+		pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+	}
+	else
+	{
+		if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+							 uiBaseOffset,
+							 (pMapping->uSize - uiBaseOffset),
+							 ui32Attribs,
+							 &pBuf->hOSMemHandle)!=PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSGetSubMemHandle failed"));
+			goto fail_cleanup;
+		}
+	}
+	if(pMapping->CpuVAddr)
+	{
+		pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uiBaseOffset);
+	}
+	pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + IMG_CAST_TO_DEVVADDR_UINT(uiBaseOffset);
+
+	if(ui32Flags & PVRSRV_MEM_ZERO)
+	{
+		if(!ZeroBuf(pBuf, pMapping, uSize, ui32Flags))
+		{
+			goto fail_cleanup;
+		}
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"WrapMemory: DevV=%08X CpuP=" CPUPADDR_FMT " uSize=0x%" SIZE_T_FMT_LEN "x",
+				pMapping->DevVAddr.uiAddr, pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"WrapMemory: DevV=%08X CpuP=" CPUPADDR_FMT " uSize=0x%" SIZE_T_FMT_LEN "x",
+				pBuf->DevVAddr.uiAddr, pBuf->CpuPAddr.uiAddr, uSize));
+
+	pBuf->pMapping = pMapping;
+	return IMG_TRUE;
+
+fail_cleanup:
+	if(uiBaseOffset && pBuf->hOSMemHandle)
+	{
+		OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Attribs);
+	}
+
+	/* pMapping must be valid: if the allocation failed, we'd have returned */
+	if(pMapping->CpuVAddr || pMapping->hOSMemHandle)
+	{
+		switch(pMapping->eCpuMemoryOrigin)
+		{
+			case hm_wrapped:
+				OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Attribs, pMapping->hOSMemHandle);
+				break;
+			case hm_wrapped_virtaddr:
+				OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Attribs, pMapping->hOSMemHandle);
+				break;
+			case hm_wrapped_scatter:
+				OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Attribs, pMapping->hOSMemHandle);
+				break;
+			case hm_wrapped_scatter_virtaddr:
+				OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Attribs, pMapping->hOSMemHandle);
+				break;
+			default:
+				break;
+		}
+
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+
+	return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags)
+{
+	IMG_VOID *pvCpuVAddr;
+
+	if(pBuf->CpuVAddr)
+	{
+		OSMemSet(pBuf->CpuVAddr, 0, uBytes);
+	}
+	else if(pMapping->eCpuMemoryOrigin == hm_contiguous
+			|| pMapping->eCpuMemoryOrigin == hm_wrapped)
+	{
+		pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr,
+									uBytes,
+									PVRSRV_HAP_KERNEL_ONLY
+									| (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+									IMG_NULL);
+		if(!pvCpuVAddr)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin for contiguous buffer failed"));
+			return IMG_FALSE;
+		}
+		OSMemSet(pvCpuVAddr, 0, uBytes);
+		OSUnMapPhysToLin(pvCpuVAddr,
+						 uBytes,
+						 PVRSRV_HAP_KERNEL_ONLY
+						 | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+						 IMG_NULL);
+	}
+	else
+	{
+		IMG_SIZE_T uBytesRemaining = uBytes;
+		IMG_SIZE_T uCurrentOffset = 0;
+		IMG_CPU_PHYADDR CpuPAddr;
+
+		/* Walk through the pBuf one page at a time and use
+		 * transient mappings to zero the memory */
+
+		PVR_ASSERT(pBuf->hOSMemHandle);
+
+		while(uBytesRemaining > 0)
+		{
+			IMG_SIZE_T uBlockBytes = MIN(uBytesRemaining, HOST_PAGESIZE());
+			CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, uCurrentOffset);
+			/* If the CpuPAddr isn't page aligned then start by writing up to the next page
+			 * boundary (or uBytesRemaining if less), so that subsequent iterations can
+			 * copy full physical pages. */
+			if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
+			{
+				uBlockBytes =
+					MIN(uBytesRemaining, (IMG_UINT32)(HOST_PAGEALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr));
+			}
+
+			pvCpuVAddr = OSMapPhysToLin(CpuPAddr,
+										uBlockBytes,
+										PVRSRV_HAP_KERNEL_ONLY
+										| (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+										IMG_NULL);
+			if(!pvCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED"));
+				return IMG_FALSE;
+			}
+			OSMemSet(pvCpuVAddr, 0, uBlockBytes);
+			OSUnMapPhysToLin(pvCpuVAddr,
+							 uBlockBytes,
+							 PVRSRV_HAP_KERNEL_ONLY
+							 | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+							 IMG_NULL);
+
+			uBytesRemaining -= uBlockBytes;
+			uCurrentOffset += uBlockBytes;
+		}
+	}
+
+	return IMG_TRUE;
+}
+
+/*!
+******************************************************************************
+
+	@Function	FreeBuf
+
+	@Description	Free a buffer previously allocated with BM_Alloc() or unwrap
+				one previous wrapped with BM_Wrap().
+				The buffer is identified by the buffer descriptor pBuf
+				returned at allocation. Note the double indirection when
+				passing the buffer.
+
+	
+	@Input      pBuf - buffer descriptor to free.
+	@Input      ui32Flags - flags
+	@Input      bFromAllocator - Is this being called by the
+					                 allocator?
+	@Output		pui32TimeToDevUnmap	- When not NULL, this receives time taken in
+				microseconds to unmap the buffer from Device MMU
+
+	@Return 	None.
+
+ *****************************************************************************/
+static IMG_VOID
+FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator
+			#if defined (PVRSRV_DEVMEM_TIME_STATS)
+			,IMG_UINT32 *pui32TimeToDevUnmap
+			#endif
+		)
+{
+	BM_MAPPING *pMapping;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"FreeBuf: pBuf=0x%p: DevVAddr=%08X CpuVAddr=0x%p CpuPAddr=" CPUPADDR_FMT,
+			pBuf, pBuf->DevVAddr.uiAddr,
+			pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
+
+	/* record mapping */
+	pMapping = pBuf->pMapping;
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	/* Pass in the storage where we wish to receive the device "unmap" timing info */
+	pMapping->pui32TimeToDevUnmap = pui32TimeToDevUnmap;
+
+	/* Initialise unmap timing to 'zero'. If the mapping is deleted from Device MMU
+	 * we'll get legit value on return */
+	if (pMapping->pui32TimeToDevUnmap)
+	{
+		*(pMapping->pui32TimeToDevUnmap) = 0;
+	}
+#endif
+
+	psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+	if (psDeviceNode->pfnCacheInvalidate)
+	{
+		psDeviceNode->pfnCacheInvalidate(psDeviceNode);
+	}
+
+	if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+	{
+		/* Submemhandle is required by exported mappings */
+		if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+		{
+			/* user supplied Device Virtual Address */
+			if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+			{
+				/* RAM backed allocation */
+				PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
+			}
+			else
+			{
+				/* free the mocked-up mapping */
+				OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+				pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/
+			}
+		}
+	}
+	else
+	{
+		/* BM supplied Device Virtual Address */
+		if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
+		{
+			/* Submemhandle is required by exported mappings */
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+				OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+			}
+		}
+		if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+		{
+			/* Submemhandle is required by exported mappings */
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+				/*
+					RAM backed allocation
+					Note: currently no need to distinguish between hm_env and hm_contiguous
+				*/
+				PVR_ASSERT(pBuf->ui32ExportCount == 0);
+				if (pBuf->pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+				{
+					IMG_UINT32 ui32FreeSize = sizeof(IMG_BOOL) * pBuf->pMapping->ui32NumVirtChunks;
+					IMG_PVOID pvFreePtr = pBuf->pMapping->pabMapChunk;
+					
+					/* With sparse allocations we don't go through the sub-alloc RA */
+					BM_FreeMemory(pBuf->pMapping->pBMHeap, pBuf->DevVAddr.uiAddr, pBuf->pMapping);
+					OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+							  ui32FreeSize,
+							  pvFreePtr,
+							  IMG_NULL);
+				}
+				else
+				{
+					RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+				}
+			}
+		}
+		else
+		{
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+				switch (pMapping->eCpuMemoryOrigin)
+				{
+					case hm_wrapped:
+						OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					case hm_wrapped_virtaddr:
+						OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					case hm_wrapped_scatter:
+						OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					case hm_wrapped_scatter_virtaddr:
+						OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+						break;
+					default:
+						break;
+				}
+			}
+			if (bFromAllocator)
+				DevMemoryFree (pMapping);
+
+			if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+			{
+				/* free the mocked-up mapping */
+				OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+				pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/
+			}
+		}
+	}
+
+
+	if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+	}
+}
+
+/*!
+******************************************************************************
+
+	@Function	BM_DestroyContext_AnyCb
+
+	@Description	Destroy a buffer manager heap.
+
+	@Input      psBMHeap
+
+	@Return 	PVRSRV_ERROR
+
+ *****************************************************************************/
+static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
+{
+	if(psBMHeap->ui32Attribs
+	& 	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+		|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+	{
+		if (psBMHeap->pImportArena)
+		{
+			IMG_BOOL bTestDelete = RA_TestDelete(psBMHeap->pImportArena);
+			if (!bTestDelete)
+			{
+				PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext_AnyCb: RA_TestDelete failed"));
+				return PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP;
+			}
+		}
+	}
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+	@Function	BM_DestroyContext
+
+	@Description	Destroy a buffer manager context. All allocated buffers must be
+				freed before calling this function.  This function is called
+				also to perform cleanup during aborted initialisations so it's
+				fairly careful not to assume any given resource has really been
+				created/allocated.
+
+	@Return 	PVRSRV_ERROR
+
+ *****************************************************************************/
+PVRSRV_ERROR
+BM_DestroyContext(IMG_HANDLE	hBMContext,
+				  IMG_BOOL		*pbDestroyed)
+{
+	PVRSRV_ERROR eError;
+	BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_DestroyContext"));
+
+	if (pbDestroyed != IMG_NULL)
+	{
+		*pbDestroyed = IMG_FALSE;
+	}
+
+	/*
+		Exit straight away if it's an invalid context handle
+	*/
+	if (pBMContext == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	pBMContext->ui32RefCount--;
+
+	if (pBMContext->ui32RefCount > 0)
+	{
+		/* Just return if there are more references to this context */
+		return PVRSRV_OK;
+	}
+
+	/*
+		Check whether there is a bug in the client which brought it here before
+		all the allocations have been freed.
+	*/
+	eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, &BM_DestroyContext_AnyCb);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
+		return eError;
+	}
+	else
+	{
+		/* free the device memory context */
+		eError = ResManFreeResByPtr(pBMContext->hResItem, CLEANUP_WITH_POLL);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError));
+			return eError;
+		}
+
+		/* mark context as destroyed */
+		if (pbDestroyed != IMG_NULL)
+		{
+			*pbDestroyed = IMG_TRUE;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+	@Function	BM_DestroyContextCallBack_AnyVaCb
+
+	@Description	Destroy Device memory context
+
+	@Input      psBMHeap - heap to be freed.
+    @Input      va - list of variable arguments with the following contents:
+					- psDeviceNode
+	@Return 	PVRSRV_ERROR
+
+ *****************************************************************************/
+static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+
+	/* Free up the import arenas */
+	if(psBMHeap->ui32Attribs
+	& 	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+		|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+	{
+		if (psBMHeap->pImportArena)
+		{
+			RA_Delete (psBMHeap->pImportArena);
+		}
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: backing store type unsupported"));
+		return PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE;
+	}
+
+	/* Free up the MMU Heaps */
+	psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+	/* Free Heap memory */
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+	@Function	BM_DestroyContextCallBack
+
+	@Description	Destroy Device memory context
+
+	@Input      pvParam - opaque void ptr param
+    @Input      ui32Param - opaque unsigned long param
+
+	@Return 	PVRSRV_ERROR
+
+ *****************************************************************************/
+static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID   pvParam,
+											  IMG_UINT32  ui32Param,
+											  IMG_BOOL    bDummy)
+{
+	BM_CONTEXT *pBMContext = pvParam;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	PVRSRV_ERROR eError;
+/*	BM_CONTEXT **ppBMContext;
+	BM_HEAP *psBMHeap, *psTmpBMHeap;*/
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	/*
+		Get DeviceNode from BMcontext
+	*/
+	psDeviceNode = pBMContext->psDeviceNode;
+
+	/*
+		Free the import arenas and heaps
+	*/
+	eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
+										&BM_DestroyContextCallBack_AnyVaCb,
+										psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+	/*
+		'Finalise' the MMU
+	*/
+	if (pBMContext->psMMUContext)
+	{
+		psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+	}
+
+	/*
+		Free up generic, useful resources - if they were allocated.
+	*/
+	if (pBMContext->pBufferHash)
+	{
+		HASH_Delete(pBMContext->pBufferHash);
+	}
+
+	if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+	{
+		/* Freeing the kernel context */
+		psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
+	}
+	else
+	{
+	    if (pBMContext->ppsThis != IMG_NULL)
+	    {
+		    /*
+		     * Remove context from the linked list
+		     */
+		    List_BM_CONTEXT_Remove(pBMContext);
+		}
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return PVRSRV_OK;
+}
+
+
+static IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, va_list va)
+{
+	PRESMAN_CONTEXT	hResManContext;
+	hResManContext = va_arg(va, PRESMAN_CONTEXT);
+	if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
+	{
+		/* just increment the refcount and return the memory context found for this process */
+		pBMContext->ui32RefCount++;
+		return pBMContext;
+	}
+	return IMG_NULL;
+}
+
+static IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	BM_CONTEXT *pBMContext;
+	psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+	pBMContext = va_arg(va, BM_CONTEXT*);
+	switch(psBMHeap->sDevArena.DevMemHeapType)
+	{
+		case DEVICE_MEMORY_HEAP_SHARED:
+		case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+		{
+			/* insert the heap into the device's MMU page directory/table */
+			psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
+			break;
+		}
+	}
+}
+
+/*!
+******************************************************************************
+
+	@Function	BM_CreateContext
+
+	@Description	Creates and initialises a buffer manager context. This function must be called
+				before any other buffer manager functions.
+
+	@Return 	valid BM context handle - Success
+				IMG_NULL - Failed
+
+ *****************************************************************************/
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE			*psDeviceNode,
+				 IMG_DEV_PHYADDR			*psPDDevPAddr,
+				 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+				 IMG_BOOL					*pbCreated)
+{
+	BM_CONTEXT			*pBMContext;
+/*	BM_HEAP				*psBMHeap;*/
+	DEVICE_MEMORY_INFO	*psDevMemoryInfo;
+	IMG_BOOL			bKernelContext;
+	PRESMAN_CONTEXT		hResManContext;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
+
+	if (psPerProc == IMG_NULL)
+	{
+		bKernelContext = IMG_TRUE;
+		hResManContext = psDeviceNode->hResManContext;
+	}
+	else
+	{
+		bKernelContext = IMG_FALSE;
+		hResManContext = psPerProc->hResManContext;
+	}
+
+	if (pbCreated != IMG_NULL)
+	{
+		*pbCreated = IMG_FALSE;
+	}
+
+	/* setup the device memory info. */
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+	if (bKernelContext == IMG_FALSE)
+	{
+		IMG_HANDLE res = (IMG_HANDLE) List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext,
+															&BM_CreateContext_IncRefCount_AnyVaCb,
+															hResManContext);
+		if (res)
+		{
+			return res;
+		}
+	}
+
+	/* allocate a BM context */
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof (struct _BM_CONTEXT_),
+					 (IMG_PVOID *)&pBMContext, IMG_NULL,
+					 "Buffer Manager Context") != PVRSRV_OK)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed"));
+		return IMG_NULL;
+	}
+	OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
+
+	/* store the associated devicenode */
+	pBMContext->psDeviceNode = psDeviceNode;
+
+	/* This hash table is used to store BM_Wraps in a global way */
+	/* INTEGRATION_POINT: 32 is an abitrary limit on the number of hashed BM_wraps */
+	pBMContext->pBufferHash = HASH_Create(32);
+	if (pBMContext->pBufferHash==IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: HASH_Create failed"));
+		goto cleanup;
+	}
+
+	if((IMG_NULL == psDeviceNode->pfnMMUInitialise) || (psDeviceNode->pfnMMUInitialise(psDeviceNode,
+											&pBMContext->psMMUContext,
+											psPDDevPAddr) != PVRSRV_OK))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed"));
+		goto cleanup;
+	}
+
+	if(bKernelContext)
+	{
+		/* just save the kernel context  */
+		PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
+		psDevMemoryInfo->pBMKernelContext = pBMContext;
+	}
+	else
+	{
+		/*
+			On the creation of each new context we must
+			insert the kernel context's 'shared' and 'shared_exported'
+			heaps into the new context
+			 - check the kernel context and heaps exist
+		*/
+		PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
+
+		if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid"));
+			goto cleanup;
+		}
+
+		PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+		/*
+			insert the kernel heaps structures into the new context's shared heap list
+			Note. this will include the kernel only heaps but these will not actually
+			be imported into the context nor returned to the client
+		 */
+		pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+		/*
+			insert the shared heaps into the MMU page directory/table
+			for the new context
+		*/
+		List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
+								&BM_CreateContext_InsertHeap_ForEachVaCb,
+								psDeviceNode,
+								pBMContext);
+
+		/* Finally, insert the new context into the list of BM contexts	*/
+		List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
+	}
+
+	/* Increment the refcount, as creation is successful */
+	pBMContext->ui32RefCount++;
+
+	/* register with resman */
+	pBMContext->hResItem = ResManRegisterRes(hResManContext,
+											RESMAN_TYPE_DEVICEMEM_CONTEXT,
+											pBMContext,
+											0,
+											&BM_DestroyContextCallBack);
+	if (pBMContext->hResItem == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: ResManRegisterRes failed"));
+		goto cleanup;
+	}
+
+	if (pbCreated != IMG_NULL)
+	{
+		*pbCreated = IMG_TRUE;
+	}
+	return (IMG_HANDLE)pBMContext;
+
+cleanup:
+	(IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0, CLEANUP_WITH_POLL);
+
+	return IMG_NULL;
+}
+
+
+static IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo;
+	psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
+	if (psBMHeap->sDevArena.ui32HeapID ==  psDevMemHeapInfo->ui32HeapID)
+	{
+		/* Match - just return already created heap */
+		return psBMHeap;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+/*!
+******************************************************************************
+
+	@Function	BM_CreateHeap
+
+	@Description	Creates and initialises a BM heap for a given BM context.
+
+	@Return 
+		valid heap handle - success
+		IMG_NULL - failure
+
+
+ *****************************************************************************/
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+			   DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
+{
+	BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	BM_HEAP *psBMHeap;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+	if(!pBMContext)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: BM_CONTEXT null"));
+		return IMG_NULL;
+	}
+
+	psDeviceNode = pBMContext->psDeviceNode;
+
+	/*
+	 * Ensure that the heap size is a multiple of the data page size.
+	 */ 
+	PVR_ASSERT((psDevMemHeapInfo->ui32HeapSize & (psDevMemHeapInfo->ui32DataPageSize - 1)) == 0);
+	PVR_ASSERT(psDevMemHeapInfo->ui32HeapSize > 0);
+
+	/*
+		We may be being asked to create a heap in a context which already has one.
+		Test for refcount > 0 because PVRSRVGetDeviceMemHeapInfoKM doesn't increment the refcount.
+		This does mean that the first call to PVRSRVCreateDeviceMemContextKM will first try to find
+		heaps that we already know don't exist
+	*/
+	if(pBMContext->ui32RefCount > 0)
+	{
+		psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
+												 &BM_CreateHeap_AnyVaCb,
+												 psDevMemHeapInfo);
+
+		if (psBMHeap)
+		{
+			return psBMHeap;
+		}
+	}
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof (BM_HEAP),
+						(IMG_PVOID *)&psBMHeap, IMG_NULL,
+						"Buffer Manager Heap") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed"));
+		return IMG_NULL;
+	}
+
+	OSMemSet (psBMHeap, 0, sizeof (BM_HEAP));
+
+	psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID;
+	psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName;
+	psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase;
+	psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize;
+	psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType;
+	psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
+	psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+	psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+#if defined(SUPPORT_MEMORY_TILING)
+	psBMHeap->ui32XTileStride = psDevMemHeapInfo->ui32XTileStride;
+#endif
+
+	/* tie the heap to the context */
+	psBMHeap->pBMContext = pBMContext;
+
+	psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
+													&psBMHeap->sDevArena,
+													&psBMHeap->pVMArena,
+													&psBMHeap->psMMUAttrib);
+	if (!psBMHeap->pMMUHeap)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+		goto ErrorExit;
+	}
+
+	/* memory is allocated from the OS as required */
+	psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
+										0, 0, IMG_NULL,
+										MIN(HOST_PAGESIZE(), psBMHeap->sDevArena.ui32DataPageSize),
+										&BM_ImportMemory,
+										&BM_FreeMemory,
+										IMG_NULL,
+										psBMHeap);
+	if(psBMHeap->pImportArena == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed"));
+		goto ErrorExit;
+	}
+
+	if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+	{
+		/*
+			memory comes from a device memory contiguous allocator (ra)
+			Note: these arenas are shared across the system so don't delete
+			as part of heap destroy
+		*/
+		psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
+		if(psBMHeap->pLocalDevMemArena == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null"));
+			goto ErrorExit;
+		}
+	}
+
+	/* insert heap into head of the heap list */
+	List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
+
+	return (IMG_HANDLE)psBMHeap;
+
+	/* handle error case */
+ErrorExit:
+
+	/* Free up the MMU if we created one */
+	if (psBMHeap->pMMUHeap != IMG_NULL)
+	{
+		psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+		/* don't finalise psMMUContext as we don't own it */
+	}
+
+	/* Free the Heap memory */
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+
+	return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+
+	@Function	BM_DestroyHeap
+
+	@Description	Destroys a BM heap
+
+	@Return 
+		valid heap handle - success
+		IMG_NULL - failure
+
+
+ *****************************************************************************/
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
+{
+	BM_HEAP* psBMHeap = (BM_HEAP*)hDevMemHeap;
+	PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap"));
+
+	if(psBMHeap)
+	{
+		/* Free up the import arenas */
+		if(psBMHeap->ui32Attribs
+		&	(PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+			|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+		{
+			if (psBMHeap->pImportArena)
+			{
+				RA_Delete (psBMHeap->pImportArena);
+			}
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: backing store type unsupported"));
+			return;
+		}
+
+		/* Free up the MMU Heap */
+		psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+
+		/* remove from the heap list */
+		List_BM_HEAP_Remove(psBMHeap);
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle"));
+	}
+}
+
+
+/*!
+******************************************************************************
+
+	@Function	BM_Reinitialise
+
+	@Description	Reinitialise the buffer manager after a power down event.
+
+	@Return 	IMG_TRUE - Success
+				IMG_FALSE - Failed
+
+ *****************************************************************************/
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+        /* FIXME: Need to reenable all contexts
+	  List_BM_CONTEXT_ForEach(psDeviceNode->sDevMemoryInfo.pBMContext, MMU_Enable);
+        */
+
+	return IMG_TRUE;
+}
+
+/*!
+******************************************************************************
+
+	@Function   BM_Alloc
+
+	@Description	Allocate a buffer mapped into both cpu and device virtual
+				memory maps.
+
+	@Input      hDevMemHeap
+	@Input      psDevVAddr - device virtual address specified by caller (optional)
+	@Input      uSize - require size in bytes of the buffer.
+	@Input      pui32Flags - bit mask of buffer property flags.
+    @Input      uDevVAddrAlignment - required alignment in bytes, or 0.
+    @Input      pvPrivData - opaque private data passed through to allocator
+    @Input      ui32PrivDataLength - length of opaque private data
+
+	@Output     phBuf - receives buffer handle
+	@Output     pui32Flags - bit mask of heap property flags.
+
+	@Return 	IMG_TRUE - Success
+				IMG_FALSE - Failure
+
+ *****************************************************************************/
+IMG_BOOL
+BM_Alloc (  IMG_HANDLE			hDevMemHeap,
+			IMG_DEV_VIRTADDR	*psDevVAddr,
+			IMG_SIZE_T			uSize,
+			IMG_UINT32			*pui32Flags,
+			IMG_UINT32			uDevVAddrAlignment,
+			IMG_PVOID			pvPrivData,
+			IMG_UINT32			ui32PrivDataLength,
+			IMG_UINT32			ui32ChunkSize,
+			IMG_UINT32			ui32NumVirtChunks,
+			IMG_UINT32			ui32NumPhysChunks,
+			IMG_BOOL			*pabMapChunk,
+			#if defined (PVRSRV_DEVMEM_TIME_STATS)
+			IMG_UINT32			*pui32TimeToDevMap,
+			#endif
+			BM_HANDLE			*phBuf)
+{
+	BM_BUF *pBuf;
+	BM_CONTEXT *pBMContext;
+	BM_HEAP *psBMHeap;
+	SYS_DATA *psSysData;
+	IMG_UINT32 ui32Flags;
+
+	if (pui32Flags == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter"));
+		PVR_DBG_BREAK;
+		return IMG_FALSE;
+	}
+
+	ui32Flags = *pui32Flags;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		  "BM_Alloc (uSize=0x%" SIZE_T_FMT_LEN "x, ui32Flags=0x%x, uDevVAddrAlignment=0x%x)",
+			uSize, ui32Flags, uDevVAddrAlignment));
+
+	SysAcquireData(&psSysData);
+
+	psBMHeap = (BM_HEAP*)hDevMemHeap;
+	pBMContext = psBMHeap->pBMContext;
+
+	if(uDevVAddrAlignment == 0)
+	{
+		uDevVAddrAlignment = 1;
+	}
+
+	/*
+	 * Allocate something in which to record the allocation's details.
+	 */
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				   sizeof (BM_BUF),
+				   (IMG_PVOID *)&pBuf, IMG_NULL,
+				   "Buffer Manager buffer") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"));
+		return IMG_FALSE;
+	}
+	OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+	/*
+	 * Allocate the memory itself now.
+	 */
+	if (AllocMemory(pBMContext,
+					psBMHeap,
+					psDevVAddr,
+					uSize,
+					ui32Flags,
+					uDevVAddrAlignment,
+					pvPrivData,
+					ui32PrivDataLength,
+					ui32ChunkSize,
+					ui32NumVirtChunks,
+					ui32NumPhysChunks,
+					pabMapChunk,
+					#if defined (PVRSRV_DEVMEM_TIME_STATS)
+					pui32TimeToDevMap,
+					#endif
+					pBuf) != IMG_TRUE)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+		/* not nulling pointer, out of scope */
+		PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
+		return IMG_FALSE;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		  "BM_Alloc (uSize=0x%" SIZE_T_FMT_LEN "x, ui32Flags=0x%x)",
+		  uSize, ui32Flags));
+
+	/*
+	 * Assign the handle and return.
+	 */
+	pBuf->ui32RefCount = 1;
+	*phBuf = (BM_HANDLE)pBuf;
+	*pui32Flags = ui32Flags | psBMHeap->ui32Attribs;
+
+	/*
+	 * If the user has specified heap CACHETYPE flags themselves,
+	 * override any CACHETYPE flags inherited from the heap.
+	 */
+	if(ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+	{
+		*pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+		*pui32Flags |= (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+	}
+
+	return IMG_TRUE;
+}
+
+
+
+#if defined(PVR_LMA)
+/*!
+******************************************************************************
+
+	@Function   ValidSysPAddrArrayForDev
+
+	@Description    Verify the array of system address is accessible
+                    by the given device.
+
+	@Input      psDeviceNode
+    @Input      psSysPAddr - system address array
+    @Input      uPageSize - size of address array
+    
+	@Return     IMG_BOOL
+
+ *****************************************************************************/
+static IMG_BOOL
+ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T uPageSize)
+{
+	IMG_UINT32 i;
+
+	for (i = 0; i < ui32PageCount; i++)
+	{
+		IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i];
+		IMG_SYS_PHYADDR sEndSysPAddr;
+
+		if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+		{
+			return IMG_FALSE;
+		}
+
+		sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + uPageSize;
+
+		if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+		{
+			return IMG_FALSE;
+		}
+	}
+
+	return IMG_TRUE;
+}
+
+/*!
+******************************************************************************
+
+	@Function  ValidSysPAddrRangeForDev
+
+	@Description   Verify a system address range is accessible
+		   by the given device.
+
+	@Input      psDeviceNode
+    @Input      sStartSysPAddr - starting system address
+    @Input      ui32Range - length of address range
+
+	@Return     IMG_BOOL
+
+ *****************************************************************************/
+static IMG_BOOL
+ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T uRange)
+{
+	IMG_SYS_PHYADDR sEndSysPAddr;
+
+	if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+	{
+		return IMG_FALSE;
+	}
+
+	sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + uRange;
+
+	if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+	{
+		return IMG_FALSE;
+	}
+
+	return IMG_TRUE;
+}
+
+#define	WRAP_MAPPING_SIZE(uByteSize, uPageOffset) HOST_PAGEALIGN((uByteSize) + (uPageOffset))
+
+#define	WRAP_PAGE_COUNT(uByteSize, uPageOffset, uHostPageSize)	(WRAP_MAPPING_SIZE(uByteSize, uPageOffset) / (uHostPageSize))
+
+#endif
+
+
+/*!
+******************************************************************************
+
+	@Function   BM_Wrap
+
+	@Description	Create a buffer which wraps user provided system physical
+				memory.
+				The wrapped memory must be page aligned. BM_Wrap will
+				roundup the size to a multiple of cpu pages.
+
+	@Input      uSize - size of memory to wrap.
+	@Input      ui32Offset - Offset into page of memory to wrap.
+	@Input      bPhysContig - Is the wrap physically contiguous.
+	@Input      psSysAddr - list of system physical page addresses of memory to wrap.
+	@Input      pvCPUVAddr - optional CPU kernel virtual address (Page aligned) of memory to wrap.
+    @Input      ui32Flags - bit mask of buffer property flags.
+    @output     phBuf - receives the buffer handle.
+
+	@Return 	IMG_TRUE - Success.
+				IMG_FALSE - Failed
+
+ *****************************************************************************/
+IMG_BOOL
+BM_Wrap (	IMG_HANDLE hDevMemHeap,
+			IMG_SIZE_T uSize,
+			IMG_SIZE_T uOffset,
+			IMG_BOOL bPhysContig,
+			IMG_SYS_PHYADDR *psSysAddr,
+			IMG_VOID *pvCPUVAddr,
+			IMG_UINT32 *pui32Flags,
+			BM_HANDLE *phBuf)
+{
+	BM_BUF *pBuf;
+	BM_CONTEXT *psBMContext;
+	BM_HEAP *psBMHeap;
+	SYS_DATA *psSysData;
+	IMG_SYS_PHYADDR sHashAddress;
+	IMG_UINT32 ui32Flags;
+
+	psBMHeap = (BM_HEAP*)hDevMemHeap;
+	psBMContext = psBMHeap->pBMContext;
+
+	ui32Flags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+	if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0))
+	{
+		ui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+		ui32Flags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK;
+	}
+
+	if ((pui32Flags != IMG_NULL) && ((*pui32Flags & (PVRSRV_MEM_READ | PVRSRV_MEM_WRITE)) != 0))
+	{
+		ui32Flags &= ~(PVRSRV_MEM_READ | PVRSRV_MEM_WRITE);
+		ui32Flags |= *pui32Flags & (PVRSRV_MEM_READ | PVRSRV_MEM_WRITE);
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		  "BM_Wrap (uSize=0x%" SIZE_T_FMT_LEN "x, uOffset=0x%" SIZE_T_FMT_LEN 
+		  "x, bPhysContig=0x%x, syspAddr=0x" SYSPADDR_FMT ", pvCPUVAddr=0x%p, ui32Flags=0x%x)",
+			uSize, 
+            uOffset, 
+            bPhysContig, 
+			psSysAddr->uiAddr,
+            pvCPUVAddr, 
+            ui32Flags));
+
+	SysAcquireData(&psSysData);
+
+#if defined(PVR_LMA)
+	if (bPhysContig)
+	{
+		if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(uSize, uOffset)))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device"));
+			return IMG_FALSE;
+		}
+	}
+	else
+	{
+		IMG_SIZE_T uHostPageSize = HOST_PAGESIZE();
+
+		if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(uSize, uOffset, uHostPageSize), uHostPageSize))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device"));
+			return IMG_FALSE;
+		}
+	}
+#endif
+	/*
+	 * Insert the System Physical Address of the first page into the hash so we can optimise multiple wraps of the
+	 * same memory.
+	 */
+	sHashAddress = psSysAddr[0];
+
+	/* Add the in-page offset to ensure a unique hash */
+	sHashAddress.uiAddr += uOffset;
+
+	/* See if this address has already been wrapped, note that the cast is ok as this is only local mem */
+	pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr);
+
+	if(pBuf)
+	{
+		IMG_SIZE_T uMappingSize = HOST_PAGEALIGN (uSize + uOffset);
+
+		/* Check base address, size and contiguity type match */
+		if(pBuf->pMapping->uSize == uMappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
+														pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,
+					"BM_Wrap (Matched previous Wrap! uSize=0x%" SIZE_T_FMT_LEN "x, uOffset=0x%" SIZE_T_FMT_LEN "x, SysAddr=" SYSPADDR_FMT ")",
+					uSize, 
+                    uOffset, 
+                    sHashAddress.uiAddr));
+
+			PVRSRVBMBufIncRef(pBuf);
+			*phBuf = (BM_HANDLE)pBuf;
+			if(pui32Flags)
+				*pui32Flags = ui32Flags;
+
+			return IMG_TRUE;
+		}
+		else
+		{
+		  /* Otherwise removed that item from the hash table 
+			 (a workaround for buffer device class) */
+			HASH_Remove(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr);
+		}	
+	}
+
+	/*
+	 * Allocate something in which to record the allocation's details.
+	 */
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof (BM_BUF),
+						(IMG_PVOID *)&pBuf, IMG_NULL,
+						"Buffer Manager buffer") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"));
+		return IMG_FALSE;
+	}
+	OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+	/*
+	 * Actually perform the memory wrap.
+	 */
+	if (WrapMemory (psBMHeap, uSize, uOffset, bPhysContig, psSysAddr, pvCPUVAddr, ui32Flags, pBuf) != IMG_TRUE)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+		return IMG_FALSE;
+	}
+
+	/* Only insert the buffer in the hash table if it is contiguous - allows for optimisation of multiple wraps
+	 * of the same contiguous buffer.
+	 */
+	if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+	{
+		/* Have we calculated the right Hash key ? */
+		PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
+
+		if (!HASH_Insert (psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
+		{
+			FreeBuf (pBuf, ui32Flags, IMG_TRUE
+						#if defined (PVRSRV_DEVMEM_TIME_STATS)
+						, IMG_NULL
+						#endif
+						);
+			PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
+			return IMG_FALSE;
+		}
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"BM_Wrap (uSize=0x%" SIZE_T_FMT_LEN "x, ui32Flags=0x%x, devVAddr=%08X)",
+			uSize, ui32Flags, pBuf->DevVAddr.uiAddr));
+
+	/*
+	 * Assign the handle and return.
+	 */
+	pBuf->ui32RefCount = 1;
+	*phBuf = (BM_HANDLE)pBuf;
+	if(pui32Flags)
+	{
+		/* need to override the heap attributes SINGLE PROC to MULT_PROC. */
+		*pui32Flags = (ui32Flags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
+	}
+
+	return IMG_TRUE;
+}
+
+/*!
+******************************************************************************
+
+	@Function   BM_Export
+
+	@Description	Export a buffer previously allocated via BM_Alloc.
+
+	@Input      hBuf - buffer handle.
+	@Input      ui32Flags - flags
+
+	@Return 	None.
+
+ *****************************************************************************/
+
+IMG_VOID
+BM_Export (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVRSRVBMBufIncExport(pBuf);
+}
+
+/*!
+******************************************************************************
+ @Function	 	BM_FreeExport
+
+ @Description	Free a buffer previously exported via BM_Export.
+
+ @Input         hBuf - buffer handle.
+ @Input         ui32Flags - flags
+
+ @Return   		None.
+**************************************************************************/
+IMG_VOID
+BM_FreeExport(BM_HANDLE hBuf,
+		IMG_UINT32 ui32Flags)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVRSRVBMBufDecExport(pBuf);
+	FreeBuf (pBuf, ui32Flags, IMG_FALSE
+			#if defined (PVRSRV_DEVMEM_TIME_STATS)
+				, IMG_NULL
+			#endif
+			);
+}
+
+/*!
+******************************************************************************
+ @Function	 	BM_Free
+
+ @Description	Free a buffer previously allocated via BM_Alloc	
+
+ @Input         hBuf - buffer handle.
+ @Input         ui32Flags - flags
+
+ @Return   		None.
+**************************************************************************/
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+			IMG_UINT32 ui32Flags
+			#if defined (PVRSRV_DEVMEM_TIME_STATS)
+			,IMG_UINT32 *pui32TimeToDevUnmap
+			#endif
+		)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+	SYS_DATA *psSysData;
+	IMG_SYS_PHYADDR sHashAddr;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=0x%p)", hBuf));
+	PVR_ASSERT (pBuf!=IMG_NULL);
+
+	if (pBuf == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter"));
+		return;
+	}
+
+	SysAcquireData(&psSysData);
+
+	PVRSRVBMBufDecRef(pBuf);
+	if(pBuf->ui32RefCount == 0)
+	{
+		if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+		{
+			sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+			HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash,	(IMG_UINTPTR_T)sHashAddr.uiAddr);
+		}
+		FreeBuf (pBuf, ui32Flags, IMG_TRUE
+					#if defined(PVRSRV_DEVMEM_TIME_STATS)
+					,pui32TimeToDevUnmap
+					#endif
+				);
+	}
+}
+
+
+/*!
+******************************************************************************
+
+	@Function   BM_HandleToCpuVaddr
+
+	@Description	Retrieve the cpu virtual address associated with a buffer.
+
+	@Input      buffer handle.
+
+	@Return 	buffers cpu virtual address, or NULL if none exists
+
+ *****************************************************************************/
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+	if (pBuf == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToCpuVaddr: invalid parameter"));
+		return IMG_NULL;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"BM_HandleToCpuVaddr(h=0x%p)=0x%p",
+				hBuf, pBuf->CpuVAddr));
+	return pBuf->CpuVAddr;
+}
+
+
+/*!
+******************************************************************************
+
+	@Function   BM_HandleToDevVaddr
+
+	@Description	Retrieve the device virtual address associated with a buffer.
+
+	@Input      hBuf - buffer handle.
+
+	@Return 	buffers device virtual address.
+
+ *****************************************************************************/
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+	if (pBuf == IMG_NULL)
+	{
+		IMG_DEV_VIRTADDR	DevVAddr = {0};
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToDevVaddr: invalid parameter"));
+		return DevVAddr;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=0x%p)=%08X", hBuf, pBuf->DevVAddr.uiAddr));
+	return pBuf->DevVAddr;
+}
+
+
+/*!
+******************************************************************************
+
+	@Function   BM_HandleToSysPaddr
+
+	@Description	Retrieve the system physical address associated with a buffer.
+
+	@Input      hBuf - buffer handle.
+
+	@Return 	buffers device virtual address.
+
+ *****************************************************************************/
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+
+	if (pBuf == IMG_NULL)
+	{
+		IMG_SYS_PHYADDR	PhysAddr = {0};
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToSysPaddr: invalid parameter"));
+		return PhysAddr;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=0lx%p)=" CPUPADDR_FMT, hBuf, pBuf->CpuPAddr.uiAddr));
+	return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
+}
+
+/*!
+******************************************************************************
+
+	@Function   BM_HandleToMemOSHandle
+
+	@Description	Retrieve the underlying memory handle associated with a buffer.
+
+	@Input      hBuf - buffer handle.
+
+	@Return 	OS Specific memory handle.
+
+ *****************************************************************************/
+IMG_HANDLE
+BM_HandleToOSMemHandle(BM_HANDLE hBuf)
+{
+	BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+	PVR_ASSERT (pBuf != IMG_NULL);
+
+	if (pBuf == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_HandleToOSMemHandle: invalid parameter"));
+		return IMG_NULL;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+				"BM_HandleToOSMemHandle(h=0x%p)=0x%p",
+				hBuf, pBuf->hOSMemHandle));
+	return pBuf->hOSMemHandle;
+}
+
+/*!
+******************************************************************************
+
+	@Function   DevMemoryAlloc
+
+	@Description	Allocate device memory for a given physical/virtual memory
+				mapping.  We handle the main cases where device MMU mappings
+				are required - these are the dynamic cases: all wrappings of
+				host OS memory and host OS imports for SYS_MMU_NORMAL mode.
+
+				If no MMU support is required then we simply map device virtual
+				space as device physical space.
+
+	@Input      pBMContext  - the pager to allocate from.
+	@Output     pMapping - the mapping descriptor to be filled in for this
+					 allocation.
+	@Output     pActualSize - the actual size of the block allocated in
+					 bytes.
+	@Input      ui32Flags -  allocation flags
+	@Input      dev_vaddr_alignment - required device virtual address
+					 alignment, or 0.
+	@Output     pDevVAddr - receives the device virtual base address of the
+					 allocated block.
+	@Return 	IMG_TRUE - Success
+				IMG_FALSE - Failed.
+
+ *****************************************************************************/
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+				BM_MAPPING *pMapping,
+				IMG_SIZE_T *pActualSize,
+				IMG_UINT32 ui32Flags,
+				IMG_UINT32 dev_vaddr_alignment,
+				IMG_DEV_VIRTADDR *pDevVAddr)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+	IMG_UINT32 ui32PDumpSize = (IMG_UINT32)pMapping->uSize;
+	IMG_UINT32 ui32PDumpFlags;
+#endif
+
+	psDeviceNode = pBMContext->psDeviceNode;
+
+#ifdef PDUMP
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	ui32PDumpFlags = psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap)
+						? PDUMP_FLAGS_PERSISTENT : PDUMP_FLAGS_CONTINUOUS;
+#else
+	ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
+#endif
+#endif
+
+	if(ui32Flags & PVRSRV_MEM_INTERLEAVED)
+	{
+		/* double the size */
+		pMapping->uSize *= 2;
+	}
+
+#ifdef PDUMP
+	if(ui32Flags & PVRSRV_MEM_DUMMY)
+	{
+		/* only one page behind a dummy allocation */
+		ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+	}
+#endif
+
+	/* Check we haven't fall through a gap */
+	PVR_ASSERT(pMapping->uSizeVM != 0);
+	/* allocate device linear space */
+	if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
+									pMapping->uSizeVM,
+									pActualSize,
+									0,
+									dev_vaddr_alignment,
+									&(pMapping->DevVAddr)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc"));
+		return IMG_FALSE;
+	}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(pBMContext->psMMUContext);
+#endif
+
+#if defined(PDUMP)
+	/* pdump the memory allocate */
+	PDUMPMALLOCPAGES(&psDeviceNode->sDevId,
+					 pMapping->DevVAddr.uiAddr,
+					 pMapping->CpuVAddr,
+					 pMapping->hOSMemHandle,
+					 ui32PDumpSize,
+					 pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+					 (IMG_HANDLE)pMapping,
+					 ui32PDumpFlags);
+#endif
+
+	switch (pMapping->eCpuMemoryOrigin)
+	{
+		case hm_wrapped:
+		case hm_wrapped_virtaddr:
+		case hm_contiguous:
+		{
+			if (ui32Flags & PVRSRV_MEM_SPARSE)
+			{
+				/* Check if this device supports sparse mappings */
+				PVR_ASSERT(psDeviceNode->pfnMMUMapPagesSparse != IMG_NULL);
+				psDeviceNode->pfnMMUMapPagesSparse(pMapping->pBMHeap->pMMUHeap,
+								pMapping->DevVAddr,
+								SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+								pMapping->ui32ChunkSize,
+								pMapping->ui32NumVirtChunks,
+								pMapping->ui32NumPhysChunks,
+								pMapping->pabMapChunk,
+								ui32Flags,
+								(IMG_HANDLE)pMapping);
+			}
+			else
+			{
+				psDeviceNode->pfnMMUMapPages (	pMapping->pBMHeap->pMMUHeap,
+								pMapping->DevVAddr,
+								SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+								pMapping->uSize,
+								ui32Flags,
+								(IMG_HANDLE)pMapping);
+			}
+			*pDevVAddr = pMapping->DevVAddr;
+			break;
+		}
+		case hm_env:
+		{
+			if (ui32Flags & PVRSRV_MEM_SPARSE)
+			{
+				/* Check if this device supports sparse mappings */
+				PVR_ASSERT(psDeviceNode->pfnMMUMapShadowSparse != IMG_NULL);
+				psDeviceNode->pfnMMUMapShadowSparse(pMapping->pBMHeap->pMMUHeap,
+								pMapping->DevVAddr,
+								pMapping->ui32ChunkSize,
+								pMapping->ui32NumVirtChunks,
+								pMapping->ui32NumPhysChunks,
+								pMapping->pabMapChunk,
+								pMapping->CpuVAddr,
+								pMapping->hOSMemHandle,
+								pDevVAddr,
+								ui32Flags,
+								(IMG_HANDLE)pMapping);
+			}
+			else
+			{
+				psDeviceNode->pfnMMUMapShadow (	pMapping->pBMHeap->pMMUHeap,
+								pMapping->DevVAddr,
+								pMapping->uSize,
+								pMapping->CpuVAddr,
+								pMapping->hOSMemHandle,
+								pDevVAddr,
+								ui32Flags,
+								(IMG_HANDLE)pMapping);
+			}
+			break;
+		}
+		case hm_wrapped_scatter:
+		case hm_wrapped_scatter_virtaddr:
+		{
+			psDeviceNode->pfnMMUMapScatter (pMapping->pBMHeap->pMMUHeap,
+							pMapping->DevVAddr,
+							pMapping->psSysAddr,
+							pMapping->uSize,
+							ui32Flags,
+							(IMG_HANDLE)pMapping);
+
+			*pDevVAddr = pMapping->DevVAddr;
+			break;
+		}
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+				"Illegal value %d for pMapping->eCpuMemoryOrigin",
+				pMapping->eCpuMemoryOrigin));
+			return IMG_FALSE;
+	}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(pBMContext->psMMUContext);
+#endif
+
+	return IMG_TRUE;
+}
+
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_DEV_PHYADDR     sDevPAddr;
+#ifdef PDUMP
+	IMG_UINT32 ui32PSize;
+	IMG_UINT32 ui32PDumpFlags;
+#endif
+
+	psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+	sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr);
+
+#ifdef PDUMP
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	ui32PDumpFlags = psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap)
+						? PDUMP_FLAGS_PERSISTENT : PDUMP_FLAGS_CONTINUOUS;
+#else
+	ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
+#endif
+#endif
+
+	if (sDevPAddr.uiAddr != 0)
+	{
+#ifdef PDUMP
+		/* pdump the memory free */
+		if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+		{
+			/* physical memory size differs in the case of Dummy allocations */
+			ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+		}
+		else
+		{
+			ui32PSize = (IMG_UINT32)pMapping->uSize;
+		}
+	
+		PDUMPFREEPAGES(pMapping->pBMHeap,
+	                    pMapping->DevVAddr,
+	                    ui32PSize,
+	                    pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+	                    (IMG_HANDLE)pMapping,
+	                    (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE,
+	                    (pMapping->ui32Flags & PVRSRV_MEM_SPARSE) ? IMG_TRUE : IMG_FALSE,
+						ui32PDumpFlags);
+#endif
+	}
+	PVR_ASSERT(pMapping->uSizeVM != 0);
+	psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSizeVM));
+}
+
+/* If this array grows larger, it might be preferable to use a hashtable rather than an array. */
+#ifndef XPROC_WORKAROUND_NUM_SHAREABLES
+#define XPROC_WORKAROUND_NUM_SHAREABLES 200
+#endif
+
+#define XPROC_WORKAROUND_BAD_SHAREINDEX 0773407734
+
+#define XPROC_WORKAROUND_UNKNOWN	0
+#define XPROC_WORKAROUND_ALLOC		1
+#define XPROC_WORKAROUND_MAP		2
+
+static IMG_UINT32 gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+static IMG_UINT32 gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
+
+/* PRQA S 0686 10 */ /* force compiler to init structure */
+XPROC_DATA gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}};
+
+PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index)
+{
+	/* if you fail this assertion - did you acquire the mutex?
+	   did you call "set" exactly once?
+	   did you call "unset" exactly once per set?
+	*/
+	if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "No, it's already set!"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	gXProcWorkaroundShareIndex = ui32Index;
+	gXProcWorkaroundState = XPROC_WORKAROUND_MAP;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index)
+{
+	/* if you fail this assertion - did you acquire the mutex?
+	   did you call "set" exactly once?
+	   did you call "unset" exactly once per set?
+	*/
+	if (gXProcWorkaroundShareIndex == XPROC_WORKAROUND_BAD_SHAREINDEX)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "huh?   how can it be bad??"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	if (gXProcWorkaroundShareIndex != ui32Index)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "gXProcWorkaroundShareIndex == 0x%08x != 0x%08x == ui32Index", gXProcWorkaroundShareIndex, ui32Index));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+	gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index)
+{
+	/* if you fail this assertion - did you acquire the mutex?
+	   did you call "set" exactly once?
+	   did you call "unset" exactly once per set?
+	*/
+	if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	for (*pui32Index = 0; *pui32Index < XPROC_WORKAROUND_NUM_SHAREABLES; (*pui32Index)++)
+	{
+		if (gXProcWorkaroundShareData[*pui32Index].ui32RefCount == 0)
+		{
+			gXProcWorkaroundShareIndex = *pui32Index;
+			gXProcWorkaroundState = XPROC_WORKAROUND_ALLOC;
+			return PVRSRV_OK;
+		}
+	}
+
+	PVR_DPF((PVR_DBG_ERROR, "ran out of shared buffers"));
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static PVRSRV_ERROR
+XProcWorkaroundAllocShareable(RA_ARENA *psArena,
+                              IMG_UINT32 ui32AllocFlags,
+                              IMG_UINT32 ui32Size,
+                              IMG_UINT32 ui32PageSize,
+							  IMG_PVOID pvPrivData,
+							  IMG_UINT32 ui32PrivDataLength,
+                              IMG_VOID **ppvCpuVAddr,
+                              IMG_HANDLE *phOSMemHandle)
+{
+	if ((ui32AllocFlags & PVRSRV_MEM_XPROC) == 0)
+	{
+		PVR_DPF((PVR_DBG_VERBOSE, "XProcWorkaroundAllocShareable: bad flags"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount > 0)
+	{
+		PVR_DPF((PVR_DBG_VERBOSE,
+				 "XProcWorkaroundAllocShareable: re-using previously allocated pages"));
+
+		ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+		ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS;
+
+		if (ui32AllocFlags != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "Can't!  Flags don't match! (I had 0x%08x, you gave 0x%08x)",
+					 gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags,
+					 ui32AllocFlags));
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		if (ui32Size != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "Can't!  Size doesn't match!"));
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		if (ui32PageSize != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "Can't!  Page Size doesn't match!"));
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		*ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
+		*phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
+
+		BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
+
+		return PVRSRV_OK;
+	}
+	else
+	{
+		if (gXProcWorkaroundState != XPROC_WORKAROUND_ALLOC)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					 "XPROC workaround in bad state! About to allocate memory from non-alloc state! (%d)",
+					 gXProcWorkaroundState));
+		}
+		PVR_ASSERT(gXProcWorkaroundState == XPROC_WORKAROUND_ALLOC);
+
+		if (psArena != IMG_NULL)
+		{
+			IMG_CPU_PHYADDR sCpuPAddr;
+			IMG_SYS_PHYADDR sSysPAddr;
+
+			PVR_DPF((PVR_DBG_VERBOSE,
+					 "XProcWorkaroundAllocShareable: making a NEW allocation from local mem"));
+
+			if (!RA_Alloc (psArena,
+						   ui32Size,
+						   IMG_NULL,
+						   IMG_NULL,
+						   0,
+                           ui32PageSize,
+						   0,
+						   pvPrivData,
+						   ui32PrivDataLength,
+						   (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: RA_Alloc(0x%x) FAILED", ui32Size));
+				return PVRSRV_ERROR_OUT_OF_MEMORY;
+			}
+
+			sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+			if(OSReservePhys(sCpuPAddr,
+							 ui32Size,
+							 ui32AllocFlags,
+							 IMG_NULL,
+							 (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
+                             &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
+            {
+                PVR_DPF((PVR_DBG_ERROR,	"XProcWorkaroundAllocShareable: OSReservePhys failed"));
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].sSysPAddr = sSysPAddr;
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_VERBOSE,
+                     "XProcWorkaroundAllocShareable: making a NEW allocation from OS"));
+
+            ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+            ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS;
+
+            /* allocate pages from the OS RAM */
+            if (OSAllocPages(ui32AllocFlags,
+                             ui32Size,
+                             ui32PageSize,
+							 pvPrivData,
+							 ui32PrivDataLength,
+							 IMG_NULL,	/* FIXME: to support cross process sparse allocations */
+                             (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
+                             &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
+            {
+                PVR_DPF((PVR_DBG_ERROR,
+                         "XProcWorkaroundAllocShareable: OSAllocPages(0x%x) failed",
+                         ui32PageSize));
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+        }
+
+		gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].psArena = psArena;
+		gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags = ui32AllocFlags;
+		gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size = ui32Size;
+		gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize = ui32PageSize;
+
+		*ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
+		*phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
+
+		BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
+
+		return PVRSRV_OK;
+	}
+}
+
+static PVRSRV_ERROR XProcWorkaroundHandleToSI(IMG_HANDLE hOSMemHandle, IMG_UINT32 *pui32SI)
+{
+	IMG_UINT32 ui32SI;
+	IMG_BOOL bFound;
+	IMG_BOOL bErrorDups;
+
+	bFound = IMG_FALSE;
+	bErrorDups = IMG_FALSE;
+
+	for (ui32SI = 0; ui32SI < XPROC_WORKAROUND_NUM_SHAREABLES; ui32SI++)
+	{
+		if (gXProcWorkaroundShareData[ui32SI].ui32RefCount>0 && gXProcWorkaroundShareData[ui32SI].hOSMemHandle == hOSMemHandle)
+		{
+			if (bFound)
+			{
+				bErrorDups = IMG_TRUE;
+			}
+			else
+			{
+				*pui32SI = ui32SI;
+				bFound = IMG_TRUE;
+			}
+		}
+	}
+
+	if (bErrorDups || !bFound)
+	{
+		return PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE;
+	}
+
+	return PVRSRV_OK;
+}
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index)
+#endif
+{
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+	PVRSRVBMXProcIncRef2(pszFile, iLine, ui32Index);
+#else
+	PVRSRVBMXProcIncRef(ui32Index);
+#endif
+}
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index)
+#endif
+{
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+	PVRSRVBMXProcDecRef2(pszFile, iLine, ui32Index);
+#else
+	PVRSRVBMXProcDecRef(ui32Index);
+#endif
+
+	PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d",
+			 ui32Index, gXProcWorkaroundShareData[ui32Index].ui32RefCount+1, gXProcWorkaroundShareData[ui32Index].ui32RefCount));
+
+	if (gXProcWorkaroundShareData[ui32Index].ui32RefCount == 0)
+	{
+		if (gXProcWorkaroundShareData[ui32Index].psArena != IMG_NULL)
+		{
+			IMG_SYS_PHYADDR sSysPAddr;
+
+			if (gXProcWorkaroundShareData[ui32Index].pvCpuVAddr != IMG_NULL)
+			{
+				OSUnReservePhys(gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+								gXProcWorkaroundShareData[ui32Index].ui32Size,
+								gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+								gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
+			}
+			sSysPAddr = gXProcWorkaroundShareData[ui32Index].sSysPAddr;
+			RA_Free (gXProcWorkaroundShareData[ui32Index].psArena,
+					 (IMG_UINTPTR_T)sSysPAddr.uiAddr,
+					 IMG_FALSE);
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_VERBOSE, "freeing OS memory"));
+			OSFreePages(gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+						gXProcWorkaroundShareData[ui32Index].ui32PageSize,
+						gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+						gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
+		}
+	}
+}
+
+static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle)
+{
+	IMG_UINT32 ui32SI = (IMG_UINT32)((IMG_UINTPTR_T)hOSMemHandle & 0xffffU);
+	PVRSRV_ERROR eError;
+
+	eError = XProcWorkaroundHandleToSI(hOSMemHandle, &ui32SI);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "bad handle"));
+		return;
+	}
+
+	BM_XProcIndexRelease(ui32SI);
+}
+
+
+/*!
+******************************************************************************
+
+	@Function   BM_ImportMemory
+
+	@Description	Provide a resource allocator with a source of pages of memory
+				from the Host OS's own allocation.  Allocates a block of pages
+				larger than requested, allowing the resource allocator to
+				operate a small cache of pre allocated pages.
+
+	@Input      pH - buffer manager handle, not the void type is dictated
+					 by the generic nature of the resource allocator interface.
+	@Input      uRequestSize - requested size in bytes
+	@Output     pActualSize - receives the actual size allocated in bytes
+					 which may be >= requested size
+	@Output     ppsMapping - receives the arbitrary user reference
+					 associated with the underlying storage.
+	@Input      ui32Flags - bit mask of allocation flags
+    @Input      pvPrivData - opaque private data passed through to allocator
+    @Input      ui32PrivDataLength - length of opaque private data
+	@Output     pBase - receives a pointer to the allocated storage.
+
+	@Return 	IMG_TRUE - success
+				IMG_FALSE - failed
+
+ *****************************************************************************/
+static IMG_BOOL
+BM_ImportMemory (IMG_VOID *pH,
+			  IMG_SIZE_T uRequestSize,
+			  IMG_SIZE_T *pActualSize,
+			  BM_MAPPING **ppsMapping,
+			  IMG_UINT32 ui32Flags,
+			  IMG_PVOID pvPrivData,
+			  IMG_UINT32 ui32PrivDataLength,
+			  IMG_UINTPTR_T *pBase)
+{
+	BM_MAPPING *pMapping;
+	BM_HEAP *pBMHeap = pH;
+	BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+	IMG_BOOL bResult;
+	IMG_SIZE_T uSize;
+	IMG_SIZE_T uPSize;
+	IMG_SIZE_T uDevVAddrAlignment = 0; /* ? */
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "BM_ImportMemory (pBMContext=0x%p, uRequestSize=0x%" SIZE_T_FMT_LEN 
+			  "x, ui32Flags=0x%x, uAlign=0x%" SIZE_T_FMT_LEN "x)",
+			  pBMContext, uRequestSize, ui32Flags, uDevVAddrAlignment));
+
+	PVR_ASSERT (ppsMapping != IMG_NULL);
+	PVR_ASSERT (pBMContext != IMG_NULL);
+
+	if (ppsMapping == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter"));
+		goto fail_exit;
+	}
+
+	uSize = HOST_PAGEALIGN (uRequestSize);
+	PVR_ASSERT (uSize >= uRequestSize);
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof (BM_MAPPING),
+						(IMG_PVOID *)&pMapping, IMG_NULL,
+						"Buffer Manager Mapping") != PVRSRV_OK)
+	{
+		PVR_DPF ((PVR_DBG_ERROR, "BM_ImportMemory: failed BM_MAPPING alloc"));
+		goto fail_exit;
+	}
+
+	pMapping->hOSMemHandle = 0;
+	pMapping->CpuVAddr = 0;
+	pMapping->DevVAddr.uiAddr = 0;
+	pMapping->CpuPAddr.uiAddr = 0;
+	pMapping->uSize = uSize;
+	if ((ui32Flags & PVRSRV_MEM_SPARSE) == 0)
+	{
+		pMapping->uSizeVM = uSize;
+	}
+	pMapping->pBMHeap = pBMHeap;
+	pMapping->ui32Flags = ui32Flags;
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	pMapping->pui32TimeToDevUnmap = IMG_NULL;
+#endif
+
+	/*
+	 * If anyone wants to know, pass back the actual size of our allocation.
+	 * There could be up to an extra page's worth of memory which will be marked
+	 * as free in the RA.
+	 */
+	if (pActualSize)
+	{
+		*pActualSize = uSize;
+	}
+
+	/* if it's a dummy allocation only use one physical page */
+	if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+	{
+		uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+	}
+	else
+	{
+		uPSize = pMapping->uSize;
+	}
+
+	if (ui32Flags & PVRSRV_MEM_XPROC)
+	{
+		IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs | PVRSRV_MEM_XPROC;
+        IMG_BOOL bBadBackingStoreType;
+
+        bBadBackingStoreType = IMG_TRUE;
+
+        if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0)
+        {
+		uDevVAddrAlignment = MAX(pBMHeap->sDevArena.ui32DataPageSize, HOST_PAGESIZE());
+
+
+		if (uPSize % uDevVAddrAlignment != 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Cannot use this memory sharing workaround with allocations that might be suballocated"));
+			goto fail_mapping_alloc;
+		}
+		uDevVAddrAlignment = 0; /* FIXME: find out why it doesn't work if alignment is specified */
+
+		/* If the user has specified heap CACHETYPE flags, use them to
+		 * override the flags inherited from the heap.
+		 */
+		if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+		{
+			ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+			ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+		}
+
+		/* allocate "shared" pages. */
+		if (XProcWorkaroundAllocShareable(IMG_NULL,
+                                          ui32Attribs,
+										  (IMG_UINT32)uPSize,
+                                          pBMHeap->sDevArena.ui32DataPageSize,
+										  pvPrivData,
+										  ui32PrivDataLength,
+                                          (IMG_VOID **)&pMapping->CpuVAddr,
+                                          &pMapping->hOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"BM_ImportMemory: XProcWorkaroundAllocShareable(0x%" SIZE_T_FMT_LEN "x) failed",
+					uPSize));
+			goto fail_mapping_alloc;
+		}
+
+		/* specify how page addresses are derived */
+		/* it works just like "env" now - no need to record
+		   it as shareable, as we use the actual hOSMemHandle
+		   and only divert to our wrapper layer based on Attribs */
+		pMapping->eCpuMemoryOrigin = hm_env;
+        	bBadBackingStoreType = IMG_FALSE;
+        }
+
+        if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0)
+        {
+            uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize;
+
+            if (uPSize % uDevVAddrAlignment != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "Cannot use this memory sharing workaround with allocations that might be suballocated"));
+                goto fail_mapping_alloc;
+            }
+            uDevVAddrAlignment = 0; /* FIXME: find out why it doesn't work if alignment is specified */
+
+            /* If the user has specified heap CACHETYPE flags, use them to
+             * override the flags inherited from the heap.
+             */
+            if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+            {
+                ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+                ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+            }
+
+            /* allocate "shared" pages. */
+            if (XProcWorkaroundAllocShareable(pBMHeap->pLocalDevMemArena,
+                                              ui32Attribs,
+                                              (IMG_UINT32)uPSize,
+                                              pBMHeap->sDevArena.ui32DataPageSize,
+											  pvPrivData,
+											  ui32PrivDataLength,
+                                              (IMG_VOID **)&pMapping->CpuVAddr,
+                                              &pMapping->hOSMemHandle) != PVRSRV_OK)
+            {
+                PVR_DPF((PVR_DBG_ERROR,
+                         "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%" SIZE_T_FMT_LEN "x) failed",
+                         uPSize));
+                goto fail_mapping_alloc;
+            }
+
+            /* specify how page addresses are derived */
+            /* it works just like "env" now - no need to record
+               it as shareable, as we use the actual hOSMemHandle
+               and only divert to our wrapper layer based on Attribs */
+            pMapping->eCpuMemoryOrigin = hm_env;
+            bBadBackingStoreType = IMG_FALSE;
+        }
+
+        if (bBadBackingStoreType)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Cannot use this memory sharing workaround with this type of backing store"));
+			goto fail_mapping_alloc;
+		}
+	}
+	else
+
+	/*
+		What type of backing store do we have?
+	*/
+	if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+	{
+		IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+		/* The allocation code needs to know this is a sparse mapping */
+		if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+		{
+			ui32Attribs |= PVRSRV_MEM_SPARSE;
+		}
+
+		/* If the user has specified heap CACHETYPE flags, use them to
+		 * override the flags inherited from the heap.
+		 */
+		if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+		{
+			ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+			ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+		}
+		
+		if (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM)
+		{
+			ui32Attribs &= ~PVRSRV_MEM_ALLOCATENONCACHEDMEM;
+			ui32Attribs |= (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM);
+		}		
+		
+		/* allocate pages from the OS RAM */
+		if (OSAllocPages(ui32Attribs,
+						 uPSize,
+						 pBMHeap->sDevArena.ui32DataPageSize,
+						 pvPrivData,
+						 ui32PrivDataLength,
+						 pMapping,
+						 (IMG_VOID **)&pMapping->CpuVAddr,
+						 &pMapping->hOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"BM_ImportMemory: OSAllocPages(0x%" SIZE_T_FMT_LEN "x) failed",
+					uPSize));
+			goto fail_mapping_alloc;
+		}
+
+		/* specify how page addresses are derived */
+		pMapping->eCpuMemoryOrigin = hm_env;
+	}
+	else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+		IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+		/* The allocation code needs to know this is a sparse mapping */
+		if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+		{
+			ui32Attribs |= PVRSRV_MEM_SPARSE;
+		}
+
+		/* allocate pages from the local device memory allocator */
+		PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
+
+		/* If the user has specified heap CACHETYPE flags, use them to
+		 * override the flags inherited from the heap.
+		 */
+		if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+		{
+			ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+			ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+		}
+
+		if (!RA_Alloc (pBMHeap->pLocalDevMemArena,
+					   uPSize,
+					   IMG_NULL,
+					   IMG_NULL,
+					   0,
+					   pBMHeap->sDevArena.ui32DataPageSize,
+					   0,
+					   pvPrivData,
+					   ui32PrivDataLength,
+					   (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%" SIZE_T_FMT_LEN "x) FAILED", uPSize));
+			goto fail_mapping_alloc;
+		}
+
+		/* derive the CPU virtual address */
+		pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+		if(OSReservePhys(pMapping->CpuPAddr,
+						 uPSize,
+						 ui32Attribs,
+						 pMapping,
+						 &pMapping->CpuVAddr,
+						 &pMapping->hOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,	"BM_ImportMemory: OSReservePhys failed"));
+			goto fail_dev_mem_alloc;
+		}
+
+		/* specify how page addresses are derived */
+		pMapping->eCpuMemoryOrigin = hm_contiguous;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,	"BM_ImportMemory: Invalid backing store type"));
+		goto fail_mapping_alloc;
+	}
+
+	/*
+	 * Allocate some device memory for what we just allocated.
+	 */
+	if ((ui32Flags & PVRSRV_MEM_SPARSE) == 0)
+	{
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+		IMG_UINT64 ui64TimeStart;
+		ui64TimeStart = OSClockMonotonicus();
+#endif
+		bResult = DevMemoryAlloc (pBMContext,
+									pMapping,
+									IMG_NULL,
+									ui32Flags,
+									(IMG_UINT32)uDevVAddrAlignment,
+									&pMapping->DevVAddr);
+		if (!bResult)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"BM_ImportMemory: DevMemoryAlloc(0x%" SIZE_T_FMT_LEN "x) failed",
+					pMapping->uSize));
+			goto fail_dev_mem_alloc;
+		}
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+		pMapping->ui32TimeToDevMap = OSClockMonotonicus() - ui64TimeStart;
+#endif
+
+		/* uDevVAddrAlignment is currently set to zero so QAC generates warning which we override */
+		/* PRQA S 3356,3358 1 */
+		PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+		PVR_ASSERT(pBase);
+		*pBase = pMapping->DevVAddr.uiAddr;
+	}
+
+	*ppsMapping = pMapping;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
+	return IMG_TRUE;
+
+fail_dev_mem_alloc:
+	/* pMapping must be valid: if the allocation failed, we'd have jumped to fail_exit */
+	if (pMapping->CpuVAddr || pMapping->hOSMemHandle)
+	{
+		/* the size is double the actual size for interleaved allocations */
+		if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
+		{
+			pMapping->uSize /= 2;
+		}
+
+		if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+		{
+			uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+		}
+		else
+		{
+			uPSize = pMapping->uSize;
+		}
+
+		if (ui32Flags & PVRSRV_MEM_XPROC)
+		{
+			XProcWorkaroundFreeShareable(pMapping->hOSMemHandle);
+		}
+		else
+        if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+		{
+			OSFreePages(pBMHeap->ui32Attribs,
+						  uPSize,
+						  (IMG_VOID *)pMapping->CpuVAddr,
+						  pMapping->hOSMemHandle);
+		}
+		else
+		{
+			IMG_SYS_PHYADDR sSysPAddr;
+
+			if(pMapping->CpuVAddr)
+			{
+				OSUnReservePhys(pMapping->CpuVAddr,
+								uPSize,
+								pBMHeap->ui32Attribs,
+								pMapping->hOSMemHandle);
+			}
+			sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr);
+			RA_Free (pBMHeap->pLocalDevMemArena, (IMG_UINTPTR_T)sSysPAddr.uiAddr, IMG_FALSE);
+		}
+	}
+fail_mapping_alloc:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+fail_exit:
+	return IMG_FALSE;
+}
+
+
+/*!
+******************************************************************************
+
+	@Function   BM_FreeMemory
+
+	@Description	Free a block of pages previously allocated via
+				BM_ImportMemory.
+
+	@Input      h - buffer manager handle, not the void type as dictated by
+						 the generic nature of the resource allocator interface.
+	@Input      _base - base address of blocks to free.
+	@Input      psMapping - arbitrary user reference associated with the
+					 underlying storage provided by BM_ImportMemory
+	@Return 	None
+
+ *****************************************************************************/
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
+{
+	BM_HEAP *pBMHeap = h;
+	IMG_SIZE_T uPSize;
+
+	PVR_UNREFERENCED_PARAMETER (_base);
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "BM_FreeMemory (h=0x%p, base=0x" UINTPTR_FMT ", psMapping=0x%p)",
+			  h, _base, psMapping));
+
+	PVR_ASSERT (psMapping != IMG_NULL);
+
+	if (psMapping == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+		return;
+	}
+
+	/*
+		Only free the virtual memory if we got as far a allocating it.
+		This NULL check should be safe as we always have a guard page
+		at virtual address 0x00000000
+	*/
+	if (psMapping->DevVAddr.uiAddr)
+	{
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+		unsigned long ulTimeStart = 0;
+		if (psMapping->pui32TimeToDevUnmap)
+		{
+			/* NON-NULL pointer signifies user has provided space to get timings info in */
+			ulTimeStart = OSClockMonotonicus();
+		}
+#endif
+		DevMemoryFree (psMapping);
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+		if (psMapping->pui32TimeToDevUnmap)
+		{
+			*(psMapping->pui32TimeToDevUnmap) = OSClockMonotonicus() - ulTimeStart;
+		}
+#endif
+	}
+
+	/* the size is double the actual for interleaved */
+	if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
+	{
+		psMapping->uSize /= 2;
+	}
+
+	if(psMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+	{
+		uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize;
+	}
+	else
+	{
+		uPSize = psMapping->uSize;
+	}
+
+	if (psMapping->ui32Flags & PVRSRV_MEM_XPROC)
+	{
+		XProcWorkaroundFreeShareable(psMapping->hOSMemHandle);
+	}
+	else
+    if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+	{
+		OSFreePages(pBMHeap->ui32Attribs,
+						uPSize,
+						(IMG_VOID *) psMapping->CpuVAddr,
+						psMapping->hOSMemHandle);
+	}
+	else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+
+		OSUnReservePhys(psMapping->CpuVAddr, uPSize, pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+		sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+		RA_Free (pBMHeap->pLocalDevMemArena, (IMG_UINTPTR_T)sSysPAddr.uiAddr, IMG_FALSE);
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,	"BM_FreeMemory: Invalid backing store type"));
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"..BM_FreeMemory (h=0x%p, base=0x" UINTPTR_FMT ")",
+			h, _base));
+}
+
+/*!
+******************************************************************************
+
+ @Function	BM_GetPhysPageAddr
+
+ @Description
+
+ @Input		psMemInfo
+
+ @Input		sDevVPageAddr
+
+ @Output	psDevPAddr
+
+ @Return	IMG_VOID
+
+******************************************************************************/
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								IMG_DEV_VIRTADDR sDevVPageAddr,
+								IMG_DEV_PHYADDR *psDevPAddr)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
+
+	PVR_ASSERT(psMemInfo && psDevPAddr);
+
+	/* check it's a page address */
+	PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+	/* PRQA S 0505 4 */ /* PVR_ASSERT should catch NULL ptrs */
+	psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+	*psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
+												sDevVPageAddr);
+}
+
+
+/*!
+******************************************************************************
+ @Function	BM_GetMMUContext
+
+ @Description	utility function to return the MMU context
+
+ @Input     hDevMemHeap - the Dev mem heap handle
+
+ @Return	MMU context, else NULL
+**************************************************************************/
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
+{
+	BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
+
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext"));
+
+	return pBMHeap->pBMContext->psMMUContext;
+}
+
+/*!
+******************************************************************************
+ @Function	BM_GetMMUContextFromMemContext
+
+ @Description	utility function to return the MMU context
+
+ @Input     hDevMemContext - the Dev mem context handle
+
+ @Return	MMU context, else NULL
+**************************************************************************/
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
+{
+	BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
+
+	PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext"));
+
+	return pBMContext->psMMUContext;
+}
+
+/*!
+******************************************************************************
+ @Function	BM_GetMMUHeap
+
+ @Description	utility function to return the MMU heap handle
+
+ @Input     hDevMemHeap - the Dev mem heap handle
+
+ @Return	MMU heap handle, else NULL
+**************************************************************************/
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
+{
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
+
+	return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap;
+}
+
+
+/*!
+******************************************************************************
+ @Function	BM_GetDeviceNode
+
+ @Description	utility function to return the devicenode from the BM Context
+
+ @Input     hDevMemContext - the Dev Mem Context
+
+ @Return	MMU heap handle, else NULL
+**************************************************************************/
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
+{
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
+
+	return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode;
+}
+
+
+/*!
+******************************************************************************
+ @Function	BM_GetMappingHandle
+
+ @Description	utility function to return the mapping handle from a meminfo
+
+ @Input     psMemInfo - kernel meminfo
+
+ @Return	mapping handle, else NULL
+**************************************************************************/
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
+
+	return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
+
+/*!
+******************************************************************************
+ @Function	BM_MappingHandleFromBuffer
+
+ @Description	utility function to get the BM mapping handle from a BM buffer
+
+ @Input     hBuffer - Handle to BM buffer
+
+ @Return	BM mapping handle
+**************************************************************************/
+IMG_HANDLE BM_MappingHandleFromBuffer(IMG_HANDLE hBuffer)
+{
+	BM_BUF *psBuffer;
+
+	PVR_ASSERT(hBuffer != IMG_NULL);
+	psBuffer = hBuffer;
+	return psBuffer->pMapping;
+}
+
+/*!
+******************************************************************************
+ @Function	BM_GetVirtualSize
+
+ @Description	utility function to get the VM size of a BM mapping
+
+ @Input     hBMHandle - Handle to BM mapping
+
+ @Return	VM size of mapping
+**************************************************************************/
+IMG_UINT32 BM_GetVirtualSize(IMG_HANDLE hBMHandle)
+{
+	BM_MAPPING *psMapping;
+
+	PVR_ASSERT(hBMHandle != IMG_NULL);
+	psMapping = hBMHandle;
+	return psMapping->ui32ChunkSize * psMapping->ui32NumVirtChunks;
+}
+
+/*!
+******************************************************************************
+ @Function	BM_MapPageAtOffset
+
+ @Description	utility function check if the specified offset in a BM mapping
+                is a page that needs to be mapped
+
+ @Input     hBMHandle - Handle to BM mapping
+
+ @Input     ui32Offset - Offset into allocation
+
+ @Return	IMG_TRUE if the page should be mapped
+**************************************************************************/
+IMG_BOOL BM_MapPageAtOffset(IMG_HANDLE hBMHandle, IMG_UINT32 ui32Offset)
+{
+	BM_MAPPING *psMapping;
+	IMG_UINT32 ui32ChunkIndex;
+
+	PVR_ASSERT(hBMHandle != IMG_NULL);
+	psMapping = hBMHandle;
+
+	ui32ChunkIndex = ui32Offset / psMapping->ui32ChunkSize;
+	/* Check for overrun */
+	PVR_ASSERT(ui32ChunkIndex <= psMapping->ui32NumVirtChunks);
+	return psMapping->pabMapChunk[ui32ChunkIndex];
+}
+
+/*!
+******************************************************************************
+ @Function	BM_VirtOffsetToPhysical
+
+ @Description	utility function find of physical offset of a sparse allocation
+                from its virtual offset.
+
+ @Input     hBMHandle - Handle to BM mapping
+
+ @Input     ui32VirtOffset - Virtual offset into allocation
+ 
+ @Output    pui32PhysOffset - Physical offset
+
+ @Return	IMG_TRUE if the virtual offset is physically backed
+**************************************************************************/
+IMG_BOOL BM_VirtOffsetToPhysical(IMG_HANDLE hBMHandle,
+								   IMG_UINT32 ui32VirtOffset,
+								   IMG_UINT32 *pui32PhysOffset)
+{
+	BM_MAPPING *psMapping;
+	IMG_UINT32 ui32ChunkOffset;
+	IMG_UINT32 ui32PhysOffset = 0;
+	IMG_UINT32 i;
+
+	PVR_ASSERT(hBMHandle != IMG_NULL);
+	psMapping = hBMHandle;
+
+	ui32ChunkOffset = ui32VirtOffset / psMapping->ui32ChunkSize;
+	if (!psMapping->pabMapChunk[ui32ChunkOffset])
+	{
+		return IMG_FALSE;
+	}
+
+	for (i=0;i<ui32ChunkOffset;i++)
+	{
+		if (psMapping->pabMapChunk[i])
+		{
+			ui32PhysOffset += psMapping->ui32ChunkSize;
+		}
+	}
+	*pui32PhysOffset = ui32PhysOffset;
+
+	return IMG_TRUE;
+}
+/******************************************************************************
+ End of file (buffer_manager.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/deviceclass.c b/drivers/gpu/pvr/services4/srvkm/common/deviceclass.c
new file mode 100644
index 0000000..b6ab4da
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/deviceclass.c
@@ -0,0 +1,2945 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device class services functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Kernel services functions for device class devices
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "kerneldisplay.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+
+#include "lists.h"
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include "pvr_sync_common.h"
+#endif
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+/***********************************************************************
+	Local Display Class Structures
+************************************************************************/
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+
+/*
+	Display Class Buffer Info
+*/
+typedef struct PVRSRV_DC_BUFFER_TAG
+{
+	/* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
+	PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+	struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+	struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+} PVRSRV_DC_BUFFER;
+
+/*
+	Display Device Class kernel swapchain information structure
+*/
+typedef struct PVRSRV_DC_SWAPCHAIN_TAG
+{
+	IMG_HANDLE							hExtSwapChain;
+	IMG_UINT32							ui32SwapChainID;
+	IMG_UINT32							ui32RefCount;
+	IMG_UINT32							ui32Flags;
+	PVRSRV_QUEUE_INFO					*psQueue;
+	PVRSRV_DC_BUFFER					asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+	IMG_UINT32							ui32BufferCount;
+	PVRSRV_DC_BUFFER					*psLastFlipBuffer;
+	IMG_UINT32							ui32MinSwapInterval;
+	IMG_UINT32							ui32MaxSwapInterval;
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+	PVRSRV_KERNEL_SYNC_INFO				**ppsLastSyncInfos;
+	IMG_UINT32							ui32LastNumSyncInfos;
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+	struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+	struct PVRSRV_DC_SWAPCHAIN_TAG		*psNext;
+} PVRSRV_DC_SWAPCHAIN;
+
+
+/*
+	Display Device Class kernel swapchain referecne structure
+*/
+typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
+{
+	struct PVRSRV_DC_SWAPCHAIN_TAG		*psSwapChain;
+	IMG_HANDLE							hResItem;	
+} PVRSRV_DC_SWAPCHAIN_REF;
+
+
+/*
+	Display Device Class kernel services information structure
+*/
+typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
+{
+	IMG_UINT32 							ui32RefCount;
+	IMG_UINT32							ui32DeviceID;
+	IMG_HANDLE							hExtDevice;
+	PPVRSRV_DC_SRV2DISP_KMJTABLE		psFuncTable;
+	IMG_HANDLE							hDevMemContext;
+	PVRSRV_DC_BUFFER 					sSystemBuffer;
+	struct PVRSRV_DC_SWAPCHAIN_TAG		*psDCSwapChainShared;
+} PVRSRV_DISPLAYCLASS_INFO;
+
+
+/*
+	Per-context Display Device Class kernel services information structure
+*/
+typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
+{
+	PVRSRV_DISPLAYCLASS_INFO			*psDCInfo;
+	PRESMAN_ITEM						hResItem;
+} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+
+
+/***********************************************************************
+	Local Buffer Class Structures
+************************************************************************/
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+/*
+	Buffer Class Buffer Info
+*/
+typedef struct PVRSRV_BC_BUFFER_TAG
+{
+	/* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
+	PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+	struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
+} PVRSRV_BC_BUFFER;
+
+
+/*
+	Buffer Device Class kernel services information structure
+*/
+typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
+{
+	IMG_UINT32 							ui32RefCount;
+	IMG_UINT32							ui32DeviceID;
+	IMG_HANDLE							hExtDevice;
+	PPVRSRV_BC_SRV2BUFFER_KMJTABLE		psFuncTable;
+	IMG_HANDLE							hDevMemContext;
+	/* buffer info returned from 3rd party driver */
+	IMG_UINT32							ui32BufferCount;
+	PVRSRV_BC_BUFFER 					*psBuffer;
+
+} PVRSRV_BUFFERCLASS_INFO;
+
+
+/*
+	Per-context Buffer Device Class kernel services information structure
+*/
+typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
+{
+	PVRSRV_BUFFERCLASS_INFO				*psBCInfo;
+	IMG_HANDLE							hResItem;
+} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+
+
+/*!
+******************************************************************************
+ @Function	DCDeviceHandleToDCInfo
+
+ @Description
+
+ Convert a client-visible 3rd party device class handle to an internal
+ PVRSRV_DISPLAYCLASS_INFO pointer.
+
+ @Input hDeviceKM	- handle to display class device, returned from OpenDCDevice
+
+ @Return
+ 	success: pointer to PVRSRV_DISPLAYCLASS_INFO
+ 	failure: IMG_NULL
+******************************************************************************/
+static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
+{
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+	psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+	return psDCPerContextInfo->psDCInfo;
+}
+
+
+/*!
+******************************************************************************
+ @Function	BCDeviceHandleToBCInfo
+
+ @Description
+
+ Convert a client-visible 3rd party buffer class handle to an internal
+ PVRSRV_BUFFERCLASS_INFO pointer.
+
+ @Input hDeviceKM	- handle to buffer class device, returned from OpenBCDevice
+
+ @Return
+ 	success: pointer to PVRSRV_BUFFERCLASS_INFO
+ 	failure: IMG_NULL
+******************************************************************************/
+static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
+{
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+	psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+	return psBCPerContextInfo->psBCInfo;
+}
+
+/*!
+******************************************************************************
+ @Function	PVRSRVEnumerateDCKM_ForEachVaCb
+
+ @Description
+
+ Enumerates the device node (if is of the same class as given).
+
+ @Input psDeviceNode	- The device node to be enumerated
+ 		va				- variable arguments list, with:
+							pui32DevCount	- The device count pointer (to be increased)
+							ppui32DevID		- The pointer to the device IDs pointer (to be updated and increased)
+							peDeviceClass	- The pointer to the device class of the psDeviceNode's to be enumerated.
+******************************************************************************/
+static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	IMG_UINT *pui32DevCount;
+	IMG_UINT32 **ppui32DevID;
+	PVRSRV_DEVICE_CLASS peDeviceClass;
+
+	pui32DevCount = va_arg(va, IMG_UINT*);
+	ppui32DevID = va_arg(va, IMG_UINT32**);
+	peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+
+	if	((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
+	&&	(psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT))
+	{
+		(*pui32DevCount)++;
+		if(*ppui32DevID)
+		{
+			*(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex;
+		}
+	}
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVEnumerateDCKM
+
+ @Description
+
+ Enumerates devices available in a given class.
+ On first call, pass valid ptr for pui32DevCount and IMG_NULL for pui32DevID,
+ On second call, pass same ptr for pui32DevCount and client allocated ptr
+ for pui32DevID device id list
+
+ @Input hServices 		- handle for services connection
+ @Input ui32DevClass	- device class identifier
+ @Output pui32DevCount	- number of devices available in class
+ @Output pui32DevID		- list of device ids in the device class
+
+ @Return
+ 	success: handle to matching display class device
+ 	failure: IMG_NULL
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
+								  IMG_UINT32 *pui32DevCount,
+								  IMG_UINT32 *pui32DevID )
+{
+	/*PVRSRV_DEVICE_NODE	*psDeviceNode;*/
+	IMG_UINT			ui32DevCount = 0;
+	SYS_DATA 			*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	/* search devonode list for devices in specified class and return the device ids */
+	List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+										&PVRSRVEnumerateDCKM_ForEachVaCb,
+										&ui32DevCount,
+										&pui32DevID,
+										DeviceClass);
+
+	if(pui32DevCount)
+	{
+		*pui32DevCount = ui32DevCount;
+	}
+	else if(pui32DevID == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters"));
+		return (PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRegisterDCDeviceKM
+
+ @Description
+
+ registers an external device with the system
+
+ @Input		psFuncTable		: device function table
+
+ @Output	pui32DeviceID	: unique device key (for case of multiple identical devices)
+
+ @Return	PVRSRV_ERROR 	:
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+									   IMG_UINT32 *pui32DeviceID)
+{
+	PVRSRV_DISPLAYCLASS_INFO 	*psDCInfo = IMG_NULL;
+	PVRSRV_DEVICE_NODE			*psDeviceNode = IMG_NULL;
+	SYS_DATA					*psSysData;
+
+	/*
+		IN:
+		 - name of client side ext. device driver library for subsequent loading
+		 - predefined list of callbacks into kernel ext. device driver (based on class type)
+
+		FUNCTION TASKS:
+		 - allocate display device class info structure
+		 - hang ext.device kernel callbacks on this structure (pfnKSwapToSystem)
+
+		OUT:
+		 - DEVICE_ID
+		 - pass back devinfo? no
+
+		Q&A:
+		 - DEVICE_ID passed in or allocated - assume allocate
+	*/
+
+	SysAcquireData(&psSysData);
+
+	/*
+		If we got this far we're doing dynamic enumeration
+		or first time static registration
+	*/
+
+	/* Allocate device control block */
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(*psDCInfo),
+					 (IMG_VOID **)&psDCInfo, IMG_NULL,
+					 "Display Class Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
+
+	/* setup the display device information structure */
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+					 (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
+					 "Function table for SRVKM->DISPLAY") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+	/* copy the jump table */
+	*psDCInfo->psFuncTable = *psFuncTable;
+
+	/* Allocate device node */
+	if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DEVICE_NODE),
+					 (IMG_VOID **)&psDeviceNode, IMG_NULL,
+					 "Device Node") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+	psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo;
+	psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
+	psDeviceNode->ui32RefCount = 1;
+	psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+	psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
+	psDeviceNode->psSysData = psSysData;
+
+	/* allocate a unique device id */
+	if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+		goto ErrorExit;
+	}
+	psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	if (pui32DeviceID)
+	{
+		*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	}
+
+	/* Register the device with the system */
+	SysRegisterExternalDevice(psDeviceNode);
+
+	/* and finally insert the device into the dev-list */
+	List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	if(psDCInfo->psFuncTable)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+		psDCInfo->psFuncTable = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+
+	if(psDeviceNode)
+	{
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+	}
+
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRemoveDCDeviceKM
+
+ @Description
+
+ Removes external device from services system record
+
+ @Input	   ui32DeviceIndex		: unique device key (for case of multiple identical devices)
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+	SYS_DATA					*psSysData;
+	PVRSRV_DEVICE_NODE			*psDeviceNode;
+	PVRSRV_DISPLAYCLASS_INFO	*psDCInfo;
+
+	SysAcquireData(&psSysData);
+
+	/*search the node matching the devindex and display class*/
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+		List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+									   &MatchDeviceKM_AnyVaCb,
+									   ui32DevIndex,
+									   IMG_FALSE,
+									   PVRSRV_DEVICE_CLASS_DISPLAY);
+	if (!psDeviceNode)
+	{
+		/*device not found*/
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
+		return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+	}
+
+	/* setup DCInfo ptr */
+	psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+	/*
+		The device can only be removed if there are
+		no open connections in the Services interface
+	*/
+	if(psDCInfo->ui32RefCount == 0)
+	{
+		/*
+			Remove from the device list.
+		*/
+		List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+		/* Unregister the device with the system */
+		SysRemoveExternalDevice(psDeviceNode);
+
+		/*
+			OK found a device with a matching devindex
+			remove registration information
+		*/
+		PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+		(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+		psDCInfo->psFuncTable = IMG_NULL;
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+		/*not nulling original pointer, overwritten*/
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount));
+		return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRegisterBCDeviceKM
+
+ @Description
+
+ registers an external device with the system
+
+ @Input		psFuncTable		: device function table
+ @Input		ui32DeviceIndex		: unique device key (for case of multiple identical devices)
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
+									   IMG_UINT32	*pui32DeviceID)
+{
+	PVRSRV_BUFFERCLASS_INFO	*psBCInfo = IMG_NULL;
+	PVRSRV_DEVICE_NODE		*psDeviceNode = IMG_NULL;
+	SYS_DATA				*psSysData;
+	/*
+		IN:
+		 - name of client side ext. device driver library for subsequent loading
+		 - predefined list of callbacks into kernel ext. device driver (based on class type)
+
+		FUNCTION TASKS:
+		 - allocate buffer device class info structure
+
+		OUT:
+		 - DEVICE_ID
+		 - pass back devinfo? no
+
+		Q&A:
+		 - DEVICE_ID passed in or allocated - assume allcoate
+	*/
+
+	SysAcquireData(&psSysData);
+
+	/*
+		If we got this far we're doing dynamic enumeration
+		or first time static registration
+	*/
+
+	/* Allocate device control block */
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(*psBCInfo),
+					 (IMG_VOID **)&psBCInfo, IMG_NULL,
+					 "Buffer Class Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
+
+	/* setup the buffer device information structure */
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+					 (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
+					 "Function table for SRVKM->BUFFER") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+	/* copy the jump table */
+	*psBCInfo->psFuncTable = *psFuncTable;
+
+	/* Allocate device node */
+	if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DEVICE_NODE),
+					 (IMG_VOID **)&psDeviceNode, IMG_NULL,
+					 "Device Node") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
+		goto ErrorExit;
+	}
+	OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+	psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo;
+	psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
+	psDeviceNode->ui32RefCount = 1;
+	psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+	psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
+	psDeviceNode->psSysData = psSysData;
+
+	/* allocate a unique device id */
+	if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+		goto ErrorExit;
+	}
+	psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	if (pui32DeviceID)
+	{
+		*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+	}
+
+	/* and finally insert the device into the dev-list */
+	List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	if(psBCInfo->psFuncTable)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+		psBCInfo->psFuncTable = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+	/*not nulling shared pointer, wasn't allocated to this point*/
+
+	if(psDeviceNode)
+	{
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+	}
+
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRemoveBCDeviceKM
+
+ @Description
+
+ Removes external device from services system record
+
+ @Input	   ui32DeviceIndex		: unique device key (for case of multiple identical devices)
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+	SYS_DATA					*psSysData;
+	PVRSRV_DEVICE_NODE			*psDevNode;
+	PVRSRV_BUFFERCLASS_INFO		*psBCInfo;
+
+	SysAcquireData(&psSysData);
+
+	/*search the device node with the devindex and buffer class*/
+	psDevNode = (PVRSRV_DEVICE_NODE*)
+		List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+									   &MatchDeviceKM_AnyVaCb,
+									   ui32DevIndex,
+									   IMG_FALSE,
+									   PVRSRV_DEVICE_CLASS_BUFFER);
+
+	if (!psDevNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex));
+		return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+	}
+
+	/* set-up devnode ptr */
+/*	psDevNode = *(ppsDevNode); */
+	/* setup BCInfo ptr */
+	psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
+
+	/*
+		The device can only be removed if there are
+		no open connections in the Services interface
+	*/
+	if(psBCInfo->ui32RefCount == 0)
+	{
+		/*
+			Remove from the device list.
+		*/
+		List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
+
+		/*
+			OK found a device with a matching devindex
+			remove registration information
+		*/
+		(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+		psBCInfo->psFuncTable = IMG_NULL;
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+		(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount));
+		return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVCloseDCDeviceKM
+
+ @Description
+
+ Closes a connection to the Display Class device
+
+ @Input	   hDeviceKM		: device handle
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE	hDeviceKM)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+	psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+	/* Remove the item from the resman list and trigger the callback. */
+	eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID  pvParam,
+										  IMG_UINT32 ui32Param,
+										  IMG_BOOL   bDummy)
+{
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam;
+	psDCInfo = psDCPerContextInfo->psDCInfo;
+
+	if(psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount != 0)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)",
+				&psDCInfo->sSystemBuffer.sDeviceClassBuffer,
+				psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount));
+	}
+
+	psDCInfo->ui32RefCount--;
+	if(psDCInfo->ui32RefCount == 0)
+	{
+		/* close the external device */
+		psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+		PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+
+		psDCInfo->hDevMemContext = IMG_NULL;
+		psDCInfo->hExtDevice = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVOpenDCDeviceKM
+
+ @Description
+
+ Opens a connection to the Display Class device, associating the connection
+ with a Device Memory Context for a services managed device
+
+ @Input	   psPerProc		: Per-process data
+ @Input	   ui32DeviceID		: unique device index
+ @Input	   hDevCookie		: devcookie used to derive the Device Memory
+ 								Context into BC surfaces will be mapped into
+ @Outut	   phDeviceKM		: handle to the DC device
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								   IMG_UINT32				ui32DeviceID,
+								   IMG_HANDLE				hDevCookie,
+								   IMG_HANDLE				*phDeviceKM)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR eError;
+
+	if(!phDeviceKM || !hDevCookie)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	SysAcquireData(&psSysData);
+
+	/* find the matching devicenode */
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+			List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+										   &MatchDeviceKM_AnyVaCb,
+										   ui32DeviceID,
+										   IMG_FALSE,
+										   PVRSRV_DEVICE_CLASS_DISPLAY);
+	if (!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID));
+		return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+	}
+	psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+	/*
+		Allocate the per-context DC Info before calling the external device,
+		to make error handling easier.
+	*/
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(*psDCPerContextInfo),
+				  (IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
+				  "Display Class per Context Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+	if(psDCInfo->ui32RefCount++ == 0)
+	{
+		psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+		/* store the device kernel context to map into */
+		psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+		/* create a syncinfo for the device's system surface */
+		eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+									(IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
+									&psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
+			goto ErrorExit;
+		}
+
+		/* open the external device */
+		eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
+                                                        	&psDCInfo->hExtDevice,
+								(PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
+			goto ErrorExitSyncInfo;
+		}
+
+		psDCPerContextInfo->psDCInfo = psDCInfo;
+		eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer"));
+			goto ErrorExitCloseDevice;
+		}
+		psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0;
+	}
+	else
+	{
+		psDCPerContextInfo->psDCInfo = psDCInfo;
+	}
+
+	psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													 RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+													 psDCPerContextInfo,
+													 0,
+													 &CloseDCDeviceCallBack);
+
+	/* return a reference to the DCPerContextInfo */
+	*phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
+
+	return PVRSRV_OK;
+
+ErrorExitCloseDevice:
+	psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+	
+ErrorExitSyncInfo:
+	PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+
+ErrorExit:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
+	psDCInfo->ui32RefCount = 0;
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVEnumDCFormatsKM
+
+ @Description
+
+ Enumerates the devices pixel formats
+
+ @Input	   hDeviceKM		: device handle
+ @Output   pui32Count		: number of pixel formats
+ @Output   psFormat			: format list
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
+									IMG_UINT32 *pui32Count,
+									DISPLAY_FORMAT *psFormat)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+	if(!hDeviceKM || !pui32Count || !psFormat)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	/* call into the display device driver to get info */
+	return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVEnumDCDimsKM
+
+ @Description
+
+ Enumerates the devices mode dimensions for a given pixel format
+
+ @Input	   hDeviceKM		: device handle
+ @Input	   psFormat			: pixel format
+ @Output   pui32Count		: number of dimensions
+ @Output   psDim			: dimensions list
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
+								 DISPLAY_FORMAT *psFormat,
+								 IMG_UINT32 *pui32Count,
+								 DISPLAY_DIMS *psDim)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+	if(!hDeviceKM || !pui32Count || !psFormat)	//  psDim==NULL to query number of dims
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	/* call into the display device driver to get info */
+	return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetDCSystemBufferKM
+
+ @Description
+
+ Get the primary surface and optionally return its buffer handle
+
+ @Input	   hDeviceKM		: device handle
+ @Output   phBuffer			: Optional buffer handle
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
+										IMG_HANDLE *phBuffer)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	IMG_HANDLE hExtBuffer;
+
+	if(!hDeviceKM)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	/* call into the display device driver to get info */
+	eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
+		return eError;
+	}
+
+	/* save the new info */
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+	psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
+
+	psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
+
+	/* return handle */
+	if (phBuffer)
+	{
+		*phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/******************************************************************************
+
+ @Function	PVRSRVGetDCInfoKM
+
+ @Description
+
+ Gets Display Class device Info
+
+ @Input		hDeviceKM		: device handle
+ @Output	psDisplayInfo
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
+								DISPLAY_INFO *psDisplayInfo)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_ERROR eError;
+
+	if(!hDeviceKM || !psDisplayInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	/* call into the display device driver to get info */
+	eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+	{
+		psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+
+	if(!hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psSwapChainRef = hSwapChainRef;
+
+	eError = ResManFreeResByPtr(psSwapChainRef->hResItem, CLEANUP_WITH_POLL);
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
+{
+	PVRSRV_ERROR				eError;
+	PVRSRV_DISPLAYCLASS_INFO	*psDCInfo = psSwapChain->psDCInfo;
+	IMG_UINT32 i;
+
+	/* Update shared swapchains list */
+	if( psDCInfo->psDCSwapChainShared )
+	{
+		if( psDCInfo->psDCSwapChainShared == psSwapChain )
+		{
+			psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
+		}
+		else 
+		{
+			PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+			psCurrentSwapChain = psDCInfo->psDCSwapChainShared; 		
+			while( psCurrentSwapChain->psNext )
+			{
+				if( psCurrentSwapChain->psNext != psSwapChain ) 
+				{
+					psCurrentSwapChain = psCurrentSwapChain->psNext;
+					continue;
+				}
+				psCurrentSwapChain->psNext = psSwapChain->psNext;
+				break;				
+			}
+		}
+	}
+
+	/* Destroy command queue before swapchain - it may use the swapchain when commands are flushed. */
+	PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
+
+	/* call into the display device driver to destroy a swapchain */
+	eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
+															psSwapChain->hExtSwapChain);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
+		return eError;
+	}
+
+	/* free the resources */
+	for(i=0; i<psSwapChain->ui32BufferCount; i++)
+	{
+		if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+		}
+	}
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+	if (psSwapChain->ppsLastSyncInfos)
+	{
+		for (i = 0; i < psSwapChain->ui32LastNumSyncInfos; i++)
+		{
+			if (psSwapChain->ppsLastSyncInfos[i])
+			{
+				PVRSRVKernelSyncInfoDecRef(psSwapChain->ppsLastSyncInfos[i], IMG_NULL);
+				psSwapChain->ppsLastSyncInfos[i] = IMG_NULL;
+			}
+		}
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+					psSwapChain->ppsLastSyncInfos, IMG_NULL);
+	}
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam,
+												  IMG_UINT32 ui32Param,
+												  IMG_BOOL bDummy)
+{
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	IMG_UINT32 i;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	for (i = 0; i < psSwapChainRef->psSwapChain->ui32BufferCount; i++)
+	{
+		if (psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "DestroyDCSwapChainRefCallBack: swapchain (0x%p) still mapped (ui32MemMapRefCount = %d)",
+					&psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer,
+					psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
+		}
+	}
+
+	if(--psSwapChainRef->psSwapChain->ui32RefCount == 0) 
+	{
+		eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
+	return eError;
+}
+
+static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo,
+														 IMG_UINT32 ui32SwapChainID)
+{
+	PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+
+	for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared; 
+		psCurrentSwapChain; 
+		psCurrentSwapChain = psCurrentSwapChain->psNext) 
+	{
+		if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
+			return psCurrentSwapChain;
+	}
+	return IMG_NULL;
+}
+
+static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												 PVRSRV_DC_SWAPCHAIN 		*psSwapChain, 
+												 PVRSRV_DC_SWAPCHAIN_REF 	**ppsSwapChainRef)
+{
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+
+	/* Allocate swapchain reference structre*/
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+					 (IMG_VOID **)&psSwapChainRef, IMG_NULL,
+					 "Display Class Swapchain Reference") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
+		return  PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
+
+	/* Bump refcount */
+	psSwapChain->ui32RefCount++;
+
+	/* Create reference resource */
+	psSwapChainRef->psSwapChain = psSwapChain;
+	psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+												  RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+												  psSwapChainRef,
+												  0,
+												  &DestroyDCSwapChainRefCallBack);
+	if (psSwapChainRef->hResItem == IMG_NULL)
+	{
+			PVR_DPF ((PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainRefKM: ResManRegisterRes failed"));
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
+			return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	*ppsSwapChainRef = psSwapChainRef;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA	*psPerProc,
+										IMG_HANDLE				hDeviceKM,
+										IMG_UINT32				ui32Flags,
+										DISPLAY_SURF_ATTRIBUTES	*psDstSurfAttrib,
+										DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+										IMG_UINT32				ui32BufferCount,
+										IMG_UINT32				ui32OEMFlags,
+										IMG_HANDLE				*phSwapChainRef,
+										IMG_UINT32				*pui32SwapChainID
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+										,IMG_INT32				i32TimelineFd
+#endif
+										)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+	PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+	PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+	PVRSRV_ERROR eError;
+	IMG_UINT32 i;
+	DISPLAY_INFO sDisplayInfo;
+
+	if(!hDeviceKM
+	|| !psDstSurfAttrib
+	|| !psSrcSurfAttrib
+	|| !phSwapChainRef
+	|| !pui32SwapChainID)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	OSMemSet (apsSyncData, 0, sizeof(PVRSRV_SYNC_DATA *) * PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+	if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers"));
+		return PVRSRV_ERROR_TOOMANYBUFFERS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
+	{
+		/* Query - use pui32SwapChainID as input */
+		psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
+		if( psSwapChain  ) 
+		{	
+			/* Create new reference */		   
+			eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, 
+												  psSwapChain, 
+												  &psSwapChainRef);
+			if( eError != PVRSRV_OK ) 
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+				return eError;
+			}
+
+			*phSwapChainRef = (IMG_HANDLE)psSwapChainRef;
+			return PVRSRV_OK;
+		}
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
+		return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;		
+	}
+
+	/* Allocate swapchain control structure for srvkm */
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DC_SWAPCHAIN),
+					 (IMG_VOID **)&psSwapChain, IMG_NULL,
+					 "Display Class Swapchain") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExit;
+	}
+	OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
+
+	/* Create a command queue for the swapchain	*/
+	eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
+		goto ErrorExit;
+	}
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	psQueue->i32TimelineFd = i32TimelineFd;
+#endif
+
+	/* store the Queue */
+	psSwapChain->psQueue = psQueue;
+
+	/* Create a Sync Object for each surface in the swapchain */
+	for(i=0; i<ui32BufferCount; i++)
+	{
+		eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+										psDCInfo->hDevMemContext,
+										&psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
+			goto ErrorExit;
+		}
+
+		/* setup common device class info */
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+
+		/* save off useful ptrs */
+		psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
+		psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
+
+		/* syncinfos must be passed as array of syncdata ptrs to the 3rd party driver */
+		apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+	}
+
+	psSwapChain->ui32BufferCount = ui32BufferCount;
+	psSwapChain->psDCInfo = psDCInfo;
+
+#if defined(PDUMP)
+	PDUMPCOMMENT("Allocate DC swap chain (SwapChainID == %u, BufferCount == %u)",
+			*pui32SwapChainID,
+			ui32BufferCount);
+	PDUMPCOMMENT("  Src surface dimensions == %u x %u",
+			psSrcSurfAttrib->sDims.ui32Width,
+			psSrcSurfAttrib->sDims.ui32Height);
+	PDUMPCOMMENT("  Dst surface dimensions == %u x %u",
+			psDstSurfAttrib->sDims.ui32Width,
+			psDstSurfAttrib->sDims.ui32Height);
+#endif
+
+	eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
+		return eError;
+	}
+	
+	psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval;
+	psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval;
+
+	/* call into the display device driver to create a swapchain */
+	eError =  psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+														ui32Flags,
+														psDstSurfAttrib,
+														psSrcSurfAttrib,
+														ui32BufferCount,
+														apsSyncData,
+														ui32OEMFlags,
+														&psSwapChain->hExtSwapChain,
+														&psSwapChain->ui32SwapChainID);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+		PDUMPCOMMENT("Swapchain allocation failed.");
+		goto ErrorExit;
+	}
+
+	/* Create new reference */		   
+	eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, 
+										  psSwapChain, 
+										  &psSwapChainRef);
+	if( eError != PVRSRV_OK ) 
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+		PDUMPCOMMENT("Swapchain allocation failed.");
+		goto ErrorExit;
+	}
+
+	psSwapChain->ui32RefCount = 1;
+	psSwapChain->ui32Flags = ui32Flags;
+
+	/* Save pointer in DC structure if it's shared struct */
+	if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
+	{
+   		if(! psDCInfo->psDCSwapChainShared ) 
+		{
+			psDCInfo->psDCSwapChainShared = psSwapChain;
+		} 
+		else 
+		{	
+			PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared;
+			psDCInfo->psDCSwapChainShared = psSwapChain;
+			psSwapChain->psNext = psOldHead;
+		}
+	}
+
+	/* We create swapchain - pui32SwapChainID is output */
+	*pui32SwapChainID = psSwapChain->ui32SwapChainID;
+
+	/* return the swapchain reference handle */
+	*phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
+
+	return eError;
+
+ErrorExit:
+
+	for(i=0; i<ui32BufferCount; i++)
+	{
+		if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+		}
+	}
+
+	if(psQueue)
+	{
+		PVRSRVDestroyCommandQueueKM(psQueue);
+	}
+
+	if(psSwapChain)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+	}
+
+	return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChainRef,
+								  IMG_RECT		*psRect)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+													psSwapChain->hExtSwapChain,
+													psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChainRef,
+								  IMG_RECT		*psRect)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+													psSwapChain->hExtSwapChain,
+													psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE	hDeviceKM,
+									   IMG_HANDLE	hSwapChainRef,
+									   IMG_UINT32	ui32CKColour)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+														psSwapChain->hExtSwapChain,
+														ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE	hDeviceKM,
+									   IMG_HANDLE	hSwapChainRef,
+									   IMG_UINT32	ui32CKColour)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+														psSwapChain->hExtSwapChain,
+														ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE	hDeviceKM,
+								  IMG_HANDLE	hSwapChainRef,
+								  IMG_UINT32	*pui32BufferCount,
+								  IMG_HANDLE	*phBuffer,
+								  IMG_SYS_PHYADDR *psPhyAddr)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+	IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+	PVRSRV_ERROR eError;
+	IMG_UINT32 i;
+
+	if(!hDeviceKM || !hSwapChainRef || !phBuffer || !psPhyAddr)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+	/* call into the display device driver to get info */
+	eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
+													psSwapChain->hExtSwapChain,
+													pui32BufferCount,
+													ahExtBuffer);
+
+	PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+	/*
+		populate the srvkm's buffer structure with the 3rd party buffer handles
+		and return the services buffer handles
+	*/
+	for(i=0; i<*pui32BufferCount; i++)
+	{
+		psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
+		phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hBuffer,
+									IMG_UINT32	ui32SwapInterval,
+									IMG_HANDLE	hPrivateTag,
+									IMG_UINT32	ui32ClipRectCount,
+									IMG_RECT	*psClipRect)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_BUFFER *psBuffer;
+	PVRSRV_QUEUE_INFO *psQueue;
+	DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+	IMG_UINT32 i;
+	IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+	IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+	IMG_UINT32 ui32NumSrcSyncs = 1;
+	PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+	PVRSRV_COMMAND *psCommand;
+	SYS_DATA *psSysData;
+
+	if(!hDeviceKM || !hBuffer || !psClipRect)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	/* Validate swap interval against limits */
+	if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval ||
+		ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+				 ui32SwapInterval, psBuffer->psSwapChain->ui32MinSwapInterval, psBuffer->psSwapChain->ui32MaxSwapInterval));
+		return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+	}
+
+	/* get the queue from the buffer structure */
+	psQueue = psBuffer->psSwapChain->psQueue;
+
+	/* specify the syncs */
+	apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+	if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
+		psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
+	{
+		apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+		ui32NumSrcSyncs++;
+	}
+
+	/* insert the command (header) */
+	eError = PVRSRVInsertCommandKM (psQueue,
+									&psCommand,
+									psDCInfo->ui32DeviceID,
+									ui16SwapCommandID,
+									0,
+									IMG_NULL,
+									ui32NumSrcSyncs,
+									apsSrcSync,
+									sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount),
+									IMG_NULL,
+									IMG_NULL,
+									IMG_NULL);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
+		goto Exit;
+	}
+
+	/*  setup the flip command */
+	psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+	/* Ext Device Handle */
+	psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+	/* Ext SwapChain Handle */
+	psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
+
+	/* Ext Buffer Handle (Buffer to Flip to) */
+	psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
+
+	/* private tag */
+	psFlipCmd->hPrivateTag = hPrivateTag;
+
+	/* setup the clip rects */
+	psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
+	/* cliprect memory appends the command structure */
+	psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));	// PRQA S 3305
+	/* copy the clip rects */
+	for(i=0; i<ui32ClipRectCount; i++)
+	{
+		psFlipCmd->psClipRect[i] = psClipRect[i];
+	}
+
+	/* number of vsyncs between successive flips */
+	psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+	SysAcquireData(&psSysData);
+
+	/* Because we might be composing just software surfaces, without
+	 * any SGX renders since the last frame, we won't necessarily
+	 * have cleaned/flushed the CPU caches before the buffers need
+	 * to be displayed.
+	 *
+	 * Doing so now is safe because InsertCommand bumped ROP2 on the
+	 * affected buffers (preventing more SW renders starting) but the
+	 * display won't start to process the buffers until SubmitCommand.
+	 */
+	{
+		if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+		{
+			OSFlushCPUCacheKM();
+		}
+		else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+		{
+			OSCleanCPUCacheKM();
+		}
+
+		psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+	}
+
+	/* submit the command */
+	eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
+		goto Exit;
+	}
+
+	/*
+		Schedule an MISR to process it
+	*/
+    eError = OSScheduleMISR(psSysData);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to schedule MISR"));
+		goto Exit;
+	}
+
+	/* update the last flip buffer */
+	psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+
+	if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+	{
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+	return eError;
+}
+
+typedef struct _CALLBACK_DATA_
+{
+	IMG_PVOID	pvPrivData;
+	IMG_UINT32	ui32PrivDataLength;
+	IMG_PVOID	ppvMemInfos;
+	IMG_UINT32	ui32NumMemInfos;
+} CALLBACK_DATA;
+
+static IMG_VOID FreePrivateData(IMG_HANDLE hCallbackData)
+{
+	CALLBACK_DATA *psCallbackData = hCallbackData;
+
+	if(psCallbackData->ui32PrivDataLength)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+				  psCallbackData->ui32PrivDataLength,
+				  psCallbackData->pvPrivData, IMG_NULL);
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+			  sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+			  psCallbackData->ppvMemInfos, IMG_NULL);
+	
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+			  sizeof(CALLBACK_DATA),
+			  hCallbackData, IMG_NULL);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE	hDeviceKM,
+									 IMG_HANDLE	hSwapChain,
+									 IMG_UINT32	ui32SwapInterval,
+									 PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
+									 PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
+									 IMG_UINT32	ui32NumMemSyncInfos,
+									 IMG_PVOID	pvPrivData,
+									 IMG_UINT32	ui32PrivDataLength,
+									 IMG_HANDLE	*phFence)
+{
+	IMG_UINT32 ui32NumSyncInfos = ui32NumMemSyncInfos;
+	IMG_UINT32 ui32NumMemInfos = ui32NumMemSyncInfos;
+	PVRSRV_KERNEL_SYNC_INFO **ppsCompiledSyncInfos;
+	IMG_UINT32 i, ui32NumCompiledSyncInfos;
+	DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+	CALLBACK_DATA *psCallbackData;
+	PVRSRV_QUEUE_INFO *psQueue;
+	PVRSRV_COMMAND *psCommand;
+	IMG_PVOID *ppvMemInfos;
+	PVRSRV_ERROR eError;
+	SYS_DATA *psSysData;
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	struct sync_fence *apsFence[SGX_MAX_SRC_SYNCS_TA] = {};
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	struct fence *apsFence[SGX_MAX_SRC_SYNCS_TA] = {};
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+	if(!hDeviceKM || !hSwapChain || !ppsMemInfos || !ppsSyncInfos || ui32NumMemSyncInfos < 1)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChain)->psSwapChain;
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+	/* Validate swap interval against limits */
+	if(ui32SwapInterval < psSwapChain->ui32MinSwapInterval ||
+	   ui32SwapInterval > psSwapChain->ui32MaxSwapInterval)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+				 ui32SwapInterval, psSwapChain->ui32MinSwapInterval, psSwapChain->ui32MaxSwapInterval));
+		return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+	}
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+					  sizeof(CALLBACK_DATA),
+					  (IMG_VOID **)&psCallbackData, IMG_NULL,
+					  "PVRSRVSwapToDCBuffer2KM callback data");
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	psCallbackData->pvPrivData = pvPrivData;
+	psCallbackData->ui32PrivDataLength = ui32PrivDataLength;
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+				  sizeof(void *) * ui32NumMemInfos,
+				  (void **)&ppvMemInfos, IMG_NULL,
+				  "Swap Command Meminfos") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+		psCallbackData->ppvMemInfos = IMG_NULL;
+		goto Exit;
+	}
+
+	for(i = 0; i < ui32NumMemInfos; i++)
+	{
+		ppvMemInfos[i] = ppsMemInfos[i];
+	}
+
+	psCallbackData->ppvMemInfos = ppvMemInfos;
+	psCallbackData->ui32NumMemInfos = ui32NumMemInfos;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	eError = PVRSyncFencesToSyncInfos(ppsSyncInfos, &ui32NumSyncInfos, apsFence);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: PVRSyncFencesToSyncInfos failed"));
+		goto Exit;
+	}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+	/* get the queue from the buffer structure */
+	psQueue = psSwapChain->psQueue;
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+	if(psSwapChain->ppsLastSyncInfos)
+	{
+		IMG_UINT32 ui32NumUniqueSyncInfos = psSwapChain->ui32LastNumSyncInfos;
+		IMG_BOOL *abUnique;
+		IMG_UINT32 j;
+
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  sizeof(IMG_BOOL) * psSwapChain->ui32LastNumSyncInfos,
+					  (IMG_VOID **)&abUnique, IMG_NULL,
+					  "Unique booleans") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for unique booleans"));
+			goto Exit;
+		}
+
+		for(j = 0; j < psSwapChain->ui32LastNumSyncInfos; j++)
+		{
+			abUnique[j] = IMG_TRUE;
+			for(i = 0; i < ui32NumSyncInfos; i++)
+			{
+				PVR_ASSERT(psSwapChain->ppsLastSyncInfos[j]);
+				PVR_ASSERT(ppsSyncInfos[i]);
+				if(psSwapChain->ppsLastSyncInfos[j] == ppsSyncInfos[i])
+				{
+					abUnique[j] = IMG_FALSE;
+					ui32NumUniqueSyncInfos--;
+					break;
+				}
+			}
+		}
+
+		ui32NumCompiledSyncInfos = ui32NumSyncInfos + ui32NumUniqueSyncInfos;
+
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+					  (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL,
+					  "Compiled syncinfos") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  sizeof(IMG_BOOL) * psSwapChain->ui32LastNumSyncInfos,
+					  (IMG_VOID *)abUnique, IMG_NULL);
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+			for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+				sync_fence_put(apsFence[i]);
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+			for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+				fence_put(apsFence[i]);
+#endif
+			goto Exit;
+		}
+				
+		OSMemCopy(ppsCompiledSyncInfos, ppsSyncInfos, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumSyncInfos);
+		for(j = 0, i = ui32NumSyncInfos; j < psSwapChain->ui32LastNumSyncInfos; j++)
+		{
+			if(abUnique[j])
+			{
+				ppsCompiledSyncInfos[i] = psSwapChain->ppsLastSyncInfos[j];
+				i++;
+			}
+		}
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(IMG_BOOL) * psSwapChain->ui32LastNumSyncInfos,
+				  (IMG_VOID *)abUnique, IMG_NULL);
+	}
+	else
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+	{
+		IMG_UINT32 j, ui32Missing = 0;
+
+		/* Older synchronization schemes would just pass down the syncinfos
+		 * hanging off of the meminfos. So we would expect identical lists.
+		 * However, newer drivers may send down additional synchronization
+		 * i.e. for TQ fence operations. In such a case we need to allocate
+		 * more space for the compiled syncinfos to ensure everything is
+		 * ROP2 synchronized.
+		 */
+		for(i = 0; i < ui32NumMemInfos; i++)
+		{
+			for(j = 0; j < ui32NumSyncInfos; j++)
+			{
+				if(ppsSyncInfos[j] == ppsMemInfos[i]->psKernelSyncInfo)
+					break;
+			}
+
+			if(j == ui32NumSyncInfos)
+				ui32Missing++;
+		}
+
+		if(ui32Missing)
+		{
+			IMG_UINT32 k;
+
+			ui32NumCompiledSyncInfos = ui32NumSyncInfos + ui32Missing;
+
+			if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						  sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+						  (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL,
+						  "Compiled syncinfos") != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+				for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+					sync_fence_put(apsFence[i]);
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+				for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+					fence_put(apsFence[i]);
+#endif
+				goto Exit;
+			}
+
+			for(i = 0; i < ui32NumSyncInfos; i++)
+			{
+				ppsCompiledSyncInfos[i] = ppsSyncInfos[i];
+			}
+
+			k = i;
+			for(i = 0; i < ui32NumMemInfos; i++)
+			{
+				for(j = 0; j < ui32NumSyncInfos; j++)
+				{
+					if(ppsSyncInfos[j] == ppsMemInfos[i]->psKernelSyncInfo)
+						break;
+				}
+
+				if(j == ui32NumSyncInfos)
+				{
+					/* Insert the unique one */
+					PVR_ASSERT(k < ui32NumCompiledSyncInfos);
+					ppsCompiledSyncInfos[k] = ppsMemInfos[i]->psKernelSyncInfo;
+					k++;
+				}
+			}
+
+			PVR_ASSERT(k == ui32NumCompiledSyncInfos);
+
+			/* As a further complication, if we have multiple displays, we
+			 * might see the same layer/meminfo submitted twice. This is
+			 * valid, as the layer might be needed by two separate pipes,
+			 * but we should not use the meminfo's synchronization twice
+			 * because this will deadlock the queue processor.
+			 *
+			 * For now, work over the meminfo end of the compiled syncs
+			 * list and collapse any duplicates. We can assume the fence
+			 * sync part of the array has already been de-duplicated.
+			 */
+			k = ui32NumSyncInfos;
+			for(i = ui32NumSyncInfos; i < ui32NumCompiledSyncInfos; i++)
+			{
+				/* Compare the i'th entry with all that follow */
+				for(j = i + 1; j < ui32NumCompiledSyncInfos; j++)
+				{
+					if(ppsCompiledSyncInfos[i] == ppsCompiledSyncInfos[j])
+						break;
+				}
+
+				if(j == ui32NumCompiledSyncInfos)
+				{
+					/* No duplicate found. Use this entry */
+					ppsCompiledSyncInfos[k] = ppsCompiledSyncInfos[i];
+					k++;
+				}
+			}
+			ui32NumCompiledSyncInfos = k;
+		}
+		else
+		{
+			ppsCompiledSyncInfos = ppsSyncInfos;
+			ui32NumCompiledSyncInfos = ui32NumSyncInfos;
+		}
+	}
+
+	/* insert the command (header) */
+	eError = PVRSRVInsertCommandKM (psQueue,
+									&psCommand,
+									psDCInfo->ui32DeviceID,
+									DC_FLIP_COMMAND,
+									0,
+									IMG_NULL,
+									ui32NumCompiledSyncInfos,
+									ppsCompiledSyncInfos,
+									sizeof(DISPLAYCLASS_FLIP_COMMAND2),
+									FreePrivateData,
+									psCallbackData,
+									phFence);
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	/* InsertCommand bumped the refcount on the raw sync objects, so we
+	 * can put the fences now. Even if the fences are deleted, the syncs
+	 * will persist.
+	 */
+	for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+		sync_fence_put(apsFence[i]);
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+		fence_put(apsFence[i]);
+#endif
+
+	if (ppsCompiledSyncInfos != ppsSyncInfos)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+			  (IMG_VOID *)ppsCompiledSyncInfos,
+			  IMG_NULL);
+	}
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to get space in queue"));
+		goto Exit;
+	}
+
+	/*  setup the flip command */
+	psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND2*)psCommand->pvData;
+
+	/* Ext Device Handle */
+	psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+	/* Ext SwapChain Handle */
+	psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+	/* number of vsyncs between successive flips */
+	psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+	/* Opaque private data, if supplied */
+	psFlipCmd->pvPrivData = pvPrivData;
+	psFlipCmd->ui32PrivDataLength = ui32PrivDataLength;
+
+	psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos;
+	psFlipCmd->ui32NumMemInfos = ui32NumMemInfos;
+
+	/* Even though this is "unused", we have to initialize it,
+	 * as the display controller might NULL-test it.
+	 */
+	psFlipCmd->hUnused = IMG_NULL;
+
+	SysAcquireData(&psSysData);
+
+	/* Because we might be composing just software surfaces, without
+	 * any SGX renders since the last frame, we won't necessarily
+	 * have cleaned/flushed the CPU caches before the buffers need
+	 * to be displayed.
+	 *
+	 * Doing so now is safe because InsertCommand bumped ROP2 on the
+	 * affected buffers (preventing more SW renders starting) but the
+	 * display won't start to process the buffers until SubmitCommand.
+	 */
+	{
+		if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+		{
+			OSFlushCPUCacheKM();
+		}
+		else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+		{
+			OSCleanCPUCacheKM();
+		}
+
+		psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+	}
+
+	/* submit the command */
+	PVRSRVSubmitCommandKM (psQueue, psCommand);
+
+	/* The command has been submitted and so psCallbackData will be freed by the callback */
+	psCallbackData = IMG_NULL;
+
+	/*
+		Schedule an MISR to process it
+	*/
+	OSScheduleMISR(psSysData);
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+	/* Reallocate the syncinfo list if it was too small */
+	if (psSwapChain->ui32LastNumSyncInfos < ui32NumSyncInfos)
+	{
+		if (psSwapChain->ppsLastSyncInfos)
+		{
+			for (i = 0; i < psSwapChain->ui32LastNumSyncInfos; i++)
+			{
+				if (psSwapChain->ppsLastSyncInfos[i])
+				{
+					PVRSRVKernelSyncInfoDecRef(psSwapChain->ppsLastSyncInfos[i], IMG_NULL);
+					psSwapChain->ppsLastSyncInfos[i] = IMG_NULL;
+				}
+			}
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+						psSwapChain->ppsLastSyncInfos, IMG_NULL);
+		}
+
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumSyncInfos,
+					  (IMG_VOID **)&psSwapChain->ppsLastSyncInfos, IMG_NULL,
+					  "Last syncinfos") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+			sync_fence_put(*phFence);
+			*phFence = IMG_NULL;
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+			fence_put(*phFence);
+			*phFence = IMG_NULL;
+#endif
+			goto Exit;
+		}
+	}
+
+	for (i = 0; i < psSwapChain->ui32LastNumSyncInfos; i++)
+	{
+		if (psSwapChain->ppsLastSyncInfos[i])
+		{
+			PVRSRVKernelSyncInfoDecRef(psSwapChain->ppsLastSyncInfos[i], IMG_NULL);
+			psSwapChain->ppsLastSyncInfos[i] = IMG_NULL;
+		}
+	}
+
+	psSwapChain->ui32LastNumSyncInfos = ui32NumSyncInfos;
+
+	for(i = 0; i < ui32NumSyncInfos; i++)
+	{
+		psSwapChain->ppsLastSyncInfos[i] = ppsSyncInfos[i];
+		PVRSRVKernelSyncInfoIncRef(psSwapChain->ppsLastSyncInfos[i], IMG_NULL);
+	}
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+
+Exit:
+	if (psCallbackData)
+	{
+		if(psCallbackData->ppvMemInfos)
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION,
+					  sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+					  psCallbackData->ppvMemInfos, IMG_NULL);
+		}
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP | PVRSRV_SWAP_BUFFER_ALLOCATION, sizeof(CALLBACK_DATA), psCallbackData, IMG_NULL);
+	}
+	if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+	{
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE	hDeviceKM,
+									IMG_HANDLE	hSwapChainRef)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_QUEUE_INFO *psQueue;
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	PVRSRV_DC_SWAPCHAIN *psSwapChain;
+	PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+	DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+	IMG_UINT32 ui32NumSrcSyncs = 1;
+	PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+	PVRSRV_COMMAND *psCommand;
+	IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+	IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+    SYS_DATA *psSysData;
+
+	if(!hDeviceKM || !hSwapChainRef)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+	psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
+	psSwapChain = psSwapChainRef->psSwapChain;
+
+	/*
+		If more than 1 reference to the swapchain exists then
+		ignore any request to swap to the system buffer
+	*/
+	if (psSwapChain->ui32RefCount > 1)
+	{
+		return PVRSRV_OK;
+	}
+
+	/* get the queue from the buffer structure */
+	psQueue = psSwapChain->psQueue;
+
+	/* specify the syncs */
+	apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+	if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
+	{
+		/* Make sure we don't make a double dependency on the same server */
+		if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+			ui32NumSrcSyncs++;
+		}
+	}
+
+	/* insert the command (header) */
+	eError = PVRSRVInsertCommandKM (psQueue,
+									&psCommand,
+									psDCInfo->ui32DeviceID,
+									ui16SwapCommandID,
+									0,
+									IMG_NULL,
+									ui32NumSrcSyncs,
+									apsSrcSync,
+									sizeof(DISPLAYCLASS_FLIP_COMMAND),
+									IMG_NULL,
+									IMG_NULL,
+									IMG_NULL);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
+		goto Exit;
+	}
+
+	/*  setup the flip command */
+	psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+	/* Ext Device Handle */
+	psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+	/* Ext SwapChain Handle */
+	psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+	/* Ext Buffer Handle (Buffer to Flip to) */
+	psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
+
+	/* private tag */
+	psFlipCmd->hPrivateTag = IMG_NULL;
+
+	/* setup the clip rects */
+	psFlipCmd->ui32ClipRectCount = 0;
+
+	psFlipCmd->ui32SwapInterval = 1;
+
+	/* submit the command */
+	eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command"));
+		goto Exit;
+	}
+
+	/* Schedule an MISR to process it */
+	SysAcquireData(&psSysData);
+    eError = OSScheduleMISR(psSysData);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to schedule MISR"));
+		goto Exit;
+	}
+
+	/* update the last flip buffer */
+	psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+	eError = PVRSRV_OK;
+
+Exit:
+
+	if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+	{
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRegisterSystemISRHandler
+
+ @Description
+
+ registers an external ISR to be called of the back of a system ISR
+
+ @Input	   ppfnISRHandler		: ISR pointer
+
+ @Input	   hISRHandlerData		: Callback data
+
+ @Input	   ui32ISRSourceMask	: ISR Mask
+
+ @Input	   ui32DeviceID			: unique device key
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER	pfnISRHandler,
+											 IMG_VOID			*pvISRHandlerData,
+											 IMG_UINT32			ui32ISRSourceMask,
+											 IMG_UINT32			ui32DeviceID)
+{
+	SYS_DATA 			*psSysData;
+	PVRSRV_DEVICE_NODE	*psDevNode;
+
+	PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
+
+	SysAcquireData(&psSysData);
+
+	/* Find Dev Node (just using the device id, ignore the class) */
+	psDevNode = (PVRSRV_DEVICE_NODE*)
+				List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+												&MatchDeviceKM_AnyVaCb,
+												ui32DeviceID,
+												IMG_TRUE);
+
+	if (psDevNode == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+	}
+
+	/* set up data before enabling the ISR */
+	psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
+
+	/* enable the ISR */
+	psDevNode->pfnDeviceISR	= pfnISRHandler;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSetDCState_ForEachVaCb
+
+ @Description
+
+ If the device node is a display, calls its set state function.
+
+ @Input	psDeviceNode	- the device node
+ 		va				- variable argument list with:
+				ui32State	- the state to be set.
+
+******************************************************************************/
+static
+IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+	IMG_UINT32 ui32State;
+	ui32State = va_arg(va, IMG_UINT32);
+
+	if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+	{
+		psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
+		if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice)
+		{
+			psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State);
+		}
+	}
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSetDCState
+
+ @Description
+
+ Calls the display driver(s) to put them into the specified state.
+
+ @Input	   ui32State: new DC state - one of DC_STATE_*
+
+******************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
+{
+/*	PVRSRV_DISPLAYCLASS_INFO	*psDCInfo;
+	PVRSRV_DEVICE_NODE			*psDeviceNode; */
+	SYS_DATA					*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+										&PVRSRVSetDCState_ForEachVaCb,
+										ui32State);
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+						   IMG_CPU_VIRTADDR *pVAddr)
+{
+	*pVAddr = psKernelMemInfo->pvLinAddrKM;
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+						   IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr)
+{
+	*pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset);
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+						   IMG_SIZE_T *uByteSize)
+{
+	*uByteSize = psKernelMemInfo->uAllocSize;
+	return PVRSRV_OK;
+}
+
+static IMG_BOOL
+PVRSRVDCMemInfoIsPhysContig(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	return OSMemHandleIsPhysContig(psKernelMemInfo->sMemBlk.hOSMemHandle);
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRGetDisplayClassJTable
+
+ @Description
+
+ Sets up function table for 3rd party Display Class Device to call through
+
+ @Input	   psJTable : pointer to function pointer table memory
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
+{
+	psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
+	psJTable->pfnPVRSRVRegisterDCDevice = &PVRSRVRegisterDCDeviceKM;
+	psJTable->pfnPVRSRVRemoveDCDevice = &PVRSRVRemoveDCDeviceKM;
+	psJTable->pfnPVRSRVOEMFunction = &SysOEMFunction;
+	psJTable->pfnPVRSRVRegisterCmdProcList = &PVRSRVRegisterCmdProcListKM;
+	psJTable->pfnPVRSRVRemoveCmdProcList = &PVRSRVRemoveCmdProcListKM;
+	psJTable->pfnPVRSRVCmdComplete = &PVRSRVCommandCompleteKM;
+	psJTable->pfnPVRSRVRegisterSystemISRHandler = &PVRSRVRegisterSystemISRHandler;
+	psJTable->pfnPVRSRVRegisterPowerDevice = &PVRSRVRegisterPowerDevice;
+	psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr;
+	psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr;
+	psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize;
+	psJTable->pfnPVRSRVDCMemInfoIsPhysContig = &PVRSRVDCMemInfoIsPhysContig;
+	return IMG_TRUE;
+}
+
+
+
+/******************************************************************************
+
+ @Function	PVRSRVCloseBCDeviceKM
+
+ @Description
+
+ Closes a connection to the Buffer Class device
+
+ @Input	   hDeviceKM		: device handle
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE	hDeviceKM)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+	psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+	/* Remove the item from the resman list and trigger the callback. */
+	eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID  pvParam,
+										  IMG_UINT32 ui32Param,
+										  IMG_BOOL   bDummy)
+{
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+	PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+	IMG_UINT32 i;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
+
+	psBCInfo = psBCPerContextInfo->psBCInfo;
+
+	for (i = 0; i < psBCInfo->ui32BufferCount; i++)
+	{
+		if (psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "CloseBCDeviceCallBack: buffer %d (0x%p) still mapped (ui32MemMapRefCount = %d)",
+					i,
+					&psBCInfo->psBuffer[i].sDeviceClassBuffer,
+					psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
+			return PVRSRV_ERROR_STILL_MAPPED;
+		}
+	}
+
+	psBCInfo->ui32RefCount--;
+	if(psBCInfo->ui32RefCount == 0)
+	{
+		/* close the external device */
+		psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
+
+		/* free syncinfos */
+		for(i=0; i<psBCInfo->ui32BufferCount; i++)
+		{
+			if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+			{
+				PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+			}
+		}
+
+		/* free buffers */
+		if(psBCInfo->psBuffer)
+		{
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL);
+			psBCInfo->psBuffer = IMG_NULL;
+		}
+	}
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVOpenBCDeviceKM
+
+ @Description
+
+ Opens a connection to the Buffer Class device, associating the connection
+ with a Device Memory Context for a services managed device
+
+ @Input	   psPerProc		: Per-process data
+ @Input	   ui32DeviceID		: unique device index
+ @Input	   hDevCookie		: devcookie used to derive the Device Memory
+ 								Context into BC surfaces will be mapped into
+ @Outut	   phDeviceKM		: handle to the DC device
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA	*psPerProc,
+								   IMG_UINT32				ui32DeviceID,
+								   IMG_HANDLE				hDevCookie,
+								   IMG_HANDLE				*phDeviceKM)
+{
+	PVRSRV_BUFFERCLASS_INFO	*psBCInfo;
+	PVRSRV_BUFFERCLASS_PERCONTEXT_INFO	*psBCPerContextInfo;
+	PVRSRV_DEVICE_NODE		*psDeviceNode;
+	SYS_DATA 				*psSysData;
+	IMG_UINT32 				i;
+	PVRSRV_ERROR			eError;
+
+	if(!phDeviceKM || !hDevCookie)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	SysAcquireData(&psSysData);
+
+	/* find the matching devicenode */
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+			List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+										   &MatchDeviceKM_AnyVaCb,
+										   ui32DeviceID,
+										   IMG_FALSE,
+										   PVRSRV_DEVICE_CLASS_BUFFER);
+	if (!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID));
+		return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+	}
+	psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
+
+/*
+FoundDevice:
+*/
+	/*
+		Allocate the per-context BC Info before calling the external device,
+		to make error handling easier.
+	*/
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(*psBCPerContextInfo),
+				  (IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
+				  "Buffer Class per Context Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+	if(psBCInfo->ui32RefCount++ == 0)
+	{
+		BUFFER_INFO sBufferInfo;
+
+		psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+		/* store the device kernel context to map into */
+		psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+		/* open the external device */
+		eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
+			goto ErrorExit;
+		}
+
+		/* get information about the buffers */
+		eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
+			goto ErrorExitCloseDevice;
+		}
+
+		/* interpret and store info */
+		psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
+
+		/*  allocate BC buffers */
+		eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+							  sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
+							  (IMG_VOID **)&psBCInfo->psBuffer,
+						 	  IMG_NULL,
+							  "Array of Buffer Class Buffer");
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
+			goto ErrorExitCloseDevice;
+		}
+		OSMemSet (psBCInfo->psBuffer,
+					0,
+					sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
+
+		for(i=0; i<psBCInfo->ui32BufferCount; i++)
+		{
+			/* create a syncinfo for the device's system surface */
+			eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+										psBCInfo->hDevMemContext,
+										&psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
+				goto ErrorExitBuffers;
+			}
+			
+			/*
+				get the buffers from the buffer class
+				drivers by index, passing-in the syncdata objects
+			*/
+			eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
+															i,
+															psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
+															&psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
+				goto ErrorExitBuffers;
+			}
+
+			/* setup common device class info */
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
+			psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount = 0;
+		}
+	}
+
+	psBCPerContextInfo->psBCInfo = psBCInfo;
+	psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													 RESMAN_TYPE_BUFFERCLASS_DEVICE,
+													 psBCPerContextInfo,
+													 0,
+													 &CloseBCDeviceCallBack);
+
+	/* return a reference to the BCPerContextInfo */
+	*phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
+
+	return PVRSRV_OK;
+
+ErrorExitBuffers:
+	/* free syncinfos */
+	for(i=0; i<psBCInfo->ui32BufferCount; i++)
+	{
+		if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+		{
+			PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+		}
+	}
+
+	/* free buffers */
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+	psBCInfo->psBuffer = IMG_NULL;
+
+ErrorExitCloseDevice:
+	psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
+
+ErrorExit:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
+	psBCInfo->ui32RefCount = 0;
+	return eError;
+}
+
+
+
+
+/******************************************************************************
+
+ @Function	PVRSRVGetBCInfoKM
+
+ @Description
+
+ Gets Buffer Class device Info
+
+ @Input		hDeviceKM		: device handle
+ @Output	psBufferInfo
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
+								BUFFER_INFO *psBufferInfo)
+{
+	PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+	PVRSRV_ERROR 			eError;
+
+	if(!hDeviceKM || !psBufferInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+	eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo);
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info"));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/******************************************************************************
+
+ @Function	PVRSRVGetBCBufferKM
+
+ @Description
+
+ Gets Buffer Class Buffer Handle
+
+ @Input		hDeviceKM		: device handle
+ @Output	psBufferInfo
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
+								  IMG_UINT32 ui32BufferIndex,
+								  IMG_HANDLE *phBuffer)
+{
+	PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+	if(!hDeviceKM || !phBuffer)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+	if(ui32BufferIndex < psBCInfo->ui32BufferCount)
+	{
+		*phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex];
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRGetBufferClassJTable
+
+ @Description
+
+ Sets up function table for 3rd party Buffer Class Device to call through
+
+ @Input	   psJTable : pointer to function pointer table memory
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
+{
+	psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+	psJTable->pfnPVRSRVRegisterBCDevice = &PVRSRVRegisterBCDeviceKM;
+	psJTable->pfnPVRSRVScheduleDevices = &PVRSRVScheduleDevicesKM;
+	psJTable->pfnPVRSRVRemoveBCDevice = &PVRSRVRemoveBCDeviceKM;
+
+	return IMG_TRUE;
+}
+
+/******************************************************************************
+ End of file (deviceclass.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/deviceid.h b/drivers/gpu/pvr/services4/srvkm/common/deviceid.h
new file mode 100644
index 0000000..1cf9f0f
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/deviceid.h
@@ -0,0 +1,51 @@
+/*************************************************************************/ /*!
+@Title          Device ID helpers
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __DEVICEID_H__
+#define __DEVICEID_H__
+
+#include "services.h"
+#include "syscommon.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#endif /* __DEVICEID_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/common/devicemem.c b/drivers/gpu/pvr/services4/srvkm/common/devicemem.c
new file mode 100644
index 0000000..77c5fc7
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/devicemem.c
@@ -0,0 +1,3493 @@
+/*************************************************************************/ /*!
+@Title          Device addressable memory functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device addressable memory APIs
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+#include "devicemem.h"
+
+#if defined(SUPPORT_ION)
+#include "ion.h"
+#include "env_perproc.h"
+#include "ion_sync.h"
+
+/* Start size of the g_IonSyncHash hash table */
+#define ION_SYNC_HASH_SIZE 20
+HASH_TABLE *g_psIonSyncHash = IMG_NULL;
+#endif
+
+#if defined(SUPPORT_DMABUF)
+#include "dmabuf.h"
+#include "dmabuf_sync.h"
+#include "pvr_linux_fence.h"
+
+/* Start size of the g_DmaBufSyncHash hash table */
+#define DMABUF_SYNC_HASH_SIZE 20
+HASH_TABLE *g_psDmaBufSyncHash = IMG_NULL;
+#endif
+
+#include "lists.h"
+
+/* local function prototypes */
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE		hDevCookie,
+								   IMG_HANDLE		hDevMemHeap,
+								   IMG_UINT32		ui32Flags,
+								   IMG_SIZE_T		ui32Size,
+								   IMG_SIZE_T		ui32Alignment,
+								   IMG_PVOID		pvPrivData,
+								   IMG_UINT32		ui32PrivDataLength,
+								   IMG_UINT32		ui32ChunkSize,
+								   IMG_UINT32		ui32NumVirtChunks,
+								   IMG_UINT32		ui32NumPhysChunks,
+								   IMG_BOOL			*pabMapChunk,
+								   PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+/* local structures */
+
+/*
+	structure stored in resman to store references
+	to the SRC and DST meminfo
+*/
+typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
+{
+	/* the DST meminfo created by the map */
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo;
+	/* SRC meminfo */
+	PVRSRV_KERNEL_MEM_INFO	*psSrcMemInfo;
+} RESMAN_MAP_DEVICE_MEM_DATA;
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+/*
+	map device class resman memory storage structure
+*/
+typedef struct _PVRSRV_DC_MAPINFO_
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo;
+	PVRSRV_DEVICE_NODE		*psDeviceNode;
+	IMG_UINT32				ui32RangeIndex;
+	IMG_UINT32				ui32TilingStride;
+	PVRSRV_DEVICECLASS_BUFFER	*psDeviceClassBuffer;
+} PVRSRV_DC_MAPINFO;
+
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+static IMG_UINT32 g_ui32SyncUID = 0;
+#if defined (MEM_TRACK_INFO_DEBUG)
+PVRSRV_MEM_TRACK_INFO *g_psMemTrackInfoHead = IMG_NULL;
+PVRSRV_MEM_TRACK_INFO *g_psMemTrackInfoTail = IMG_NULL;
+IMG_UINT32	g_ui32NumOfOpsRecorded = 0;
+#endif
+
+static PVRSRV_KERNEL_SYNC_INFO *g_psSyncInfoList = IMG_NULL;
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAddMemTrackInfo
+
+ @Description
+
+ Adds the current psMemTrackInfo instance to the head of list represented by gMemTrackInfo
+
+ @Input	   psMemTrackInfo :
+ @Output 
+
+ @Return
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVAddMemTrackInfo(PVRSRV_MEM_TRACK_INFO *psMemTrackInfo)
+{
+	g_ui32NumOfOpsRecorded++;
+	psMemTrackInfo->next = g_psMemTrackInfoHead;
+	psMemTrackInfo->prev = IMG_NULL;
+	if(g_psMemTrackInfoHead)
+	{
+		g_psMemTrackInfoHead->prev = psMemTrackInfo;
+	}
+	else
+		g_psMemTrackInfoTail = psMemTrackInfo;
+	g_psMemTrackInfoHead = psMemTrackInfo;
+	if(g_ui32NumOfOpsRecorded > MAX_MEM_TRACK_OPS)
+	{
+		PVRSRV_MEM_TRACK_INFO *psFreePtr;
+		psFreePtr = g_psMemTrackInfoTail;
+		g_psMemTrackInfoTail = g_psMemTrackInfoTail->prev; 
+		g_psMemTrackInfoTail->next = IMG_NULL;
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_MEM_TRACK_INFO), 
+						psFreePtr, IMG_NULL);
+		g_ui32NumOfOpsRecorded--;
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPrintMemTrackInfo
+
+ @Description
+
+ Dumps the mem tracking info
+
+ @Input	   ui32FaultAddr:
+ @Output   
+
+ @Return  
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVPrintMemTrackInfo(IMG_UINT32 ui32FaultAddr)
+{
+	PVRSRV_MEM_TRACK_INFO *psMemTrackInfo;
+	static const IMG_CHAR * const apszMemOpNames[] = {"UNKNOWN", "DEVICE", "DEVICECLASS", "WRAPPED", "MAPPED", "ION", "DMA-BUF" "ALLOC", "FREE"};
+	psMemTrackInfo = g_psMemTrackInfoHead;
+
+	PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVMemTrackInfo: Dumping mem tracking info\n"));
+	PVR_DPF((PVR_DBG_MESSAGE,"DevVAddr  |  Size  |  Memory Op | Process ID | Ref Count |   Task Name   | Heap ID | Time Stamp(uSec)\n"));
+	while(psMemTrackInfo)
+	{
+		if((ui32FaultAddr >= psMemTrackInfo->sDevVAddr.uiAddr) &&
+				(ui32FaultAddr < (psMemTrackInfo->sDevVAddr.uiAddr + psMemTrackInfo->uSize)))
+		{
+			PVR_DPF((PVR_DBG_MESSAGE,"***************************\n"));
+		}
+		PVR_DPF((PVR_DBG_MESSAGE,"0x%-8x | 0x%-8zx | %-13s | %-11d | %-6u  | %-15s | %10s | %-15u ",	
+				psMemTrackInfo->sDevVAddr.uiAddr,
+				psMemTrackInfo->uSize,
+				apszMemOpNames[psMemTrackInfo->eOp],
+				psMemTrackInfo->ui32Pid,
+				psMemTrackInfo->ui32RefCount,
+				psMemTrackInfo->asTaskName,
+				psMemTrackInfo->heapId,
+				psMemTrackInfo->ui32TimeStampUSecs));
+		psMemTrackInfo = psMemTrackInfo->next;
+	}
+}
+#endif
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetDeviceMemHeapsKM
+
+ @Description
+
+ Gets the device shared memory heaps
+
+ @Input	   hDevCookie :
+ @Output   phDevMemContext : ptr to handle to memory context
+ @Output   psHeapInfo : ptr to array of heap info
+
+ @Return   PVRSRV_DEVICE_NODE, valid devnode or IMG_NULL
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+													PVRSRV_HEAP_INFO *psHeapInfo)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_UINT32 ui32HeapCount;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_UINT32 i;
+
+	if (hDevCookie == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+	/* Setup useful pointers */
+	ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+	psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+	/* check we don't exceed the max number of heaps */
+	PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+	/* retrieve heap information */
+	for(i=0; i<ui32HeapCount; i++)
+	{
+		/* return information about the heap */
+		psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+		psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+		psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+		psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+		psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+		/* (XTileStride > 0) denotes a tiled heap */
+		psHeapInfo[i].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+	}
+
+	for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+		psHeapInfo[i].ui32HeapID = (IMG_UINT32)PVRSRV_UNDEFINED_HEAP_ID;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVCreateDeviceMemContextKM
+
+ @Description
+
+ Creates a device memory context
+
+ @Input	   hDevCookie :
+ @Input	   psPerProc : Per-process data
+ @Output   phDevMemContext : ptr to handle to memory context
+ @Output   pui32ClientHeapCount : ptr to heap count
+ @Output   psHeapInfo : ptr to array of heap info
+
+ @Return   PVRSRV_DEVICE_NODE, valid devnode or IMG_NULL
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE					hDevCookie,
+														 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+														 IMG_HANDLE 				*phDevMemContext,
+														 IMG_UINT32 				*pui32ClientHeapCount,
+														 PVRSRV_HEAP_INFO			*psHeapInfo,
+														 IMG_BOOL					*pbCreated,
+														 IMG_BOOL 					*pbShared)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_HANDLE hDevMemContext;
+	IMG_HANDLE hDevMemHeap;
+	IMG_DEV_PHYADDR sPDDevPAddr;
+	IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+	PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+	if (hDevCookie == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+	/*
+		Setup useful pointers
+	*/
+	ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+	psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+	/*
+		check we don't exceed the max number of heaps
+	*/
+	PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+	/*
+		Create a memory context for the caller
+	*/
+	hDevMemContext = BM_CreateContext(psDeviceNode,
+									  &sPDDevPAddr,
+									  psPerProc,
+									  pbCreated);
+	if (hDevMemContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* create the per context heaps */
+	for(i=0; i<ui32HeapCount; i++)
+	{
+		switch(psDeviceMemoryHeap[i].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+				/* return information about the heap */
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+				#if defined(SUPPORT_MEMORY_TILING)
+				psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+				#else
+				psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+				#endif
+
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+				ui32ClientHeapCount++;
+				break;
+			}
+			case DEVICE_MEMORY_HEAP_PERCONTEXT:
+			{
+				if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+				{
+					hDevMemHeap = BM_CreateHeap(hDevMemContext,
+												&psDeviceMemoryHeap[i]);
+					if (hDevMemHeap == IMG_NULL)
+					{
+						BM_DestroyContext(hDevMemContext, IMG_NULL);
+						return PVRSRV_ERROR_OUT_OF_MEMORY;
+					}
+				}
+				else
+				{
+					hDevMemHeap = IMG_NULL;
+				}
+
+				/* return information about the heap */
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+				#if defined(SUPPORT_MEMORY_TILING)
+				psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+				#else
+				psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+				#endif
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+				ui32ClientHeapCount++;
+				break;
+			}
+		}
+	}
+
+	/* return shared_exported and per context heap information to the caller */
+	*pui32ClientHeapCount = ui32ClientHeapCount;
+	*phDevMemContext = hDevMemContext;
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+														  IMG_HANDLE hDevMemContext,
+														  IMG_BOOL *pbDestroyed)
+{
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	return BM_DestroyContext(hDevMemContext, pbDestroyed);
+}
+
+
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetDeviceMemHeapInfoKM
+
+ @Description
+
+ gets heap info
+
+ @Input	   hDevCookie :
+ @Input    hDevMemContext : ptr to handle to memory context
+ @Output   pui32ClientHeapCount : ptr to heap count
+ @Output   psHeapInfo : ptr to array of heap info
+
+ @Return
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE					hDevCookie,
+														 IMG_HANDLE 				hDevMemContext,
+														 IMG_UINT32 				*pui32ClientHeapCount,
+														 PVRSRV_HEAP_INFO			*psHeapInfo,
+														 IMG_BOOL 					*pbShared)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_HANDLE hDevMemHeap;
+	IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+	PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+	if (hDevCookie == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+	/*
+		Setup useful pointers
+	*/
+	ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+	psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+	/*
+		check we don't exceed the max number of heaps
+	*/
+	PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+	/* create the per context heaps */
+	for(i=0; i<ui32HeapCount; i++)
+	{
+		switch(psDeviceMemoryHeap[i].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+				/* return information about the heap */
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+				psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+				ui32ClientHeapCount++;
+				break;
+			}
+			case DEVICE_MEMORY_HEAP_PERCONTEXT:
+			{
+				if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+				{
+					hDevMemHeap = BM_CreateHeap(hDevMemContext,
+												&psDeviceMemoryHeap[i]);
+				
+					if (hDevMemHeap == IMG_NULL)
+					{
+						return PVRSRV_ERROR_OUT_OF_MEMORY;
+					}
+				}
+				else
+				{
+					hDevMemHeap = IMG_NULL;
+				}
+
+				/* return information about the heap */
+				psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+				psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+				psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+				psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+				psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+				psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+#if defined(PVR_SECURE_HANDLES)
+				pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+				ui32ClientHeapCount++;
+				break;
+			}
+		}
+	}
+
+	/* return shared_exported and per context heap information to the caller */
+	*pui32ClientHeapCount = ui32ClientHeapCount;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	AllocDeviceMem
+
+ @Description
+
+ Allocates device memory
+
+ @Input	   hDevCookie :
+
+ @Input	   hDevMemHeap
+
+ @Input	   ui32Flags : Some combination of PVRSRV_MEM_ flags
+
+ @Input	   ui32Size :  Number of bytes to allocate
+
+ @Input	   ui32Alignment : Alignment of allocation
+
+ @Input    pvPrivData : Opaque private data passed through to allocator
+
+ @Input    ui32PrivDataLength : Length of opaque private data
+
+ @Output   **ppsMemInfo : On success, receives a pointer to the created MEM_INFO structure
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE		hDevCookie,
+								   IMG_HANDLE		hDevMemHeap,
+								   IMG_UINT32		ui32Flags,
+								   IMG_SIZE_T		ui32Size,
+								   IMG_SIZE_T		ui32Alignment,
+								   IMG_PVOID		pvPrivData,
+								   IMG_UINT32		ui32PrivDataLength,
+								   IMG_UINT32		ui32ChunkSize,
+								   IMG_UINT32		ui32NumVirtChunks,
+								   IMG_UINT32		ui32NumPhysChunks,
+								   IMG_BOOL			*pabMapChunk,
+								   PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ 	PVRSRV_KERNEL_MEM_INFO	*psMemInfo;
+	BM_HANDLE 		hBuffer;
+	/* Pointer to implementation details within the mem_info */
+	PVRSRV_MEMBLK	*psMemBlock;
+	IMG_BOOL		bBMError;
+
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	*ppsMemInfo = IMG_NULL;
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: Failed to alloc memory for block"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+	/* BM supplied Device Virtual Address with physical backing RAM */
+	psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+	bBMError = BM_Alloc (hDevMemHeap,
+							IMG_NULL,
+							ui32Size,
+							&psMemInfo->ui32Flags,
+							IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+							pvPrivData,
+							ui32PrivDataLength,
+							ui32ChunkSize,
+							ui32NumVirtChunks,
+							ui32NumPhysChunks,
+							pabMapChunk,
+							#if defined (PVRSRV_DEVMEM_TIME_STATS)
+							&psMemInfo->ui32TimeToDevMap,
+							#endif
+							&hBuffer);
+
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Fill in "Implementation dependant" section of mem info */
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+	/* Convert from BM_HANDLE to external IMG_HANDLE */
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+	/* Fill in the public fields of the MEM_INFO structure */
+
+	psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+
+	if (ui32Flags & PVRSRV_MEM_SPARSE)
+	{
+		psMemInfo->uAllocSize = ui32ChunkSize * ui32NumVirtChunks;
+	}
+	else
+	{
+		psMemInfo->uAllocSize = ui32Size;
+	}
+
+	/* Clear the Backup buffer pointer as we do not have one at this point. We only allocate this as we are going up/down */
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+	/*
+	 * Setup the output.
+	 */
+	*ppsMemInfo = psMemInfo;
+
+	/*
+	 * And I think we're done for now....
+	 */
+	return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
+{
+	BM_HANDLE		hBuffer;
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+	switch(eCallbackOrigin)
+	{
+		case PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR:
+			BM_Free(hBuffer,
+					psMemInfo->ui32Flags
+					#if defined(PVRSRV_DEVMEM_TIME_STATS)
+					,psMemInfo->pui32TimeToDevUnmap
+					#endif
+					);
+			break;
+		case PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER:
+			BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+			break;
+		default:
+			break;
+	}
+
+	if (psMemInfo->pvSysBackupBuffer &&
+		eCallbackOrigin == PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+		psMemInfo->pvSysBackupBuffer = IMG_NULL;
+	}
+
+	if (psMemInfo->ui32RefCount == 0)
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+	return(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	BM_HANDLE		hBuffer;
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+	BM_Free(hBuffer, psMemInfo->ui32Flags
+				#if defined(PVRSRV_DEVMEM_TIME_STATS)
+				, IMG_NULL
+				#endif
+				);
+
+	if(psMemInfo->pvSysBackupBuffer)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+		psMemInfo->pvSysBackupBuffer = IMG_NULL;
+	}
+
+	OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+	return(PVRSRV_OK);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAllocSyncInfoKM
+
+ @Description
+
+ Allocates a sync info
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE					hDevCookie,
+												IMG_HANDLE					hDevMemContext,
+												PVRSRV_KERNEL_SYNC_INFO		**ppsKernelSyncInfo)
+{
+	IMG_HANDLE hSyncDevMemHeap;
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	BM_CONTEXT *pBMContext;
+	PVRSRV_ERROR eError;
+	PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo;
+	PVRSRV_SYNC_DATA *psSyncData;
+
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_KERNEL_SYNC_INFO),
+						(IMG_VOID **)&psKernelSyncInfo, IMG_NULL,
+						"Kernel Synchronization Info");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	eError = OSAtomicAlloc(&psKernelSyncInfo->pvRefCount);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to allocate atomic"));
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	
+
+	/* Get the devnode from the devheap */
+	pBMContext = (BM_CONTEXT*)hDevMemContext;
+	psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+	/* and choose a heap for the syncinfo */
+	hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
+
+	/*
+		Cache consistent flag would be unnecessary if the heap attributes were
+		changed to specify it.
+	*/
+	eError = AllocDeviceMem(hDevCookie,
+							hSyncDevMemHeap,
+							PVRSRV_MEM_CACHE_CONSISTENT,
+							sizeof(PVRSRV_SYNC_DATA),
+							sizeof(IMG_UINT32),
+							IMG_NULL,
+							0,
+							0, 0, 0, IMG_NULL, /* Sparse mapping args, not required */
+							&psKernelSyncInfo->psSyncDataMemInfoKM);
+
+	if (eError != PVRSRV_OK)
+	{
+
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+		OSAtomicFree(psKernelSyncInfo->pvRefCount);
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* init sync data */
+	psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+	psSyncData = psKernelSyncInfo->psSyncData;
+
+	psSyncData->ui32WriteOpsPending = 0;
+	psSyncData->ui32WriteOpsComplete = 0;
+	psSyncData->ui32ReadOpsPending = 0;
+	psSyncData->ui32ReadOpsComplete = 0;
+	psSyncData->ui32ReadOps2Pending = 0;
+	psSyncData->ui32ReadOps2Complete = 0;
+	psSyncData->ui32LastOpDumpVal = 0;
+	psSyncData->ui32LastReadOpDumpVal = 0;
+	psSyncData->ui64LastWrite = 0;
+
+#if defined(SUPPORT_DMABUF)
+	psKernelSyncInfo->hFenceContext = IMG_NULL;
+#endif
+
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+	psKernelSyncInfo->ui32OperationMask = 0;
+	memset(psKernelSyncInfo->aui32OpInfo, 0, sizeof(psKernelSyncInfo->aui32OpInfo));
+	memset(psKernelSyncInfo->aui32ReadOpSample, 0, sizeof(psKernelSyncInfo->aui32ReadOpSample));
+	memset(psKernelSyncInfo->aui32WriteOpSample, 0, sizeof(psKernelSyncInfo->aui32WriteOpSample));
+	memset(psKernelSyncInfo->aui32ReadOp2Sample, 0, sizeof(psKernelSyncInfo->aui32ReadOp2Sample));
+	psKernelSyncInfo->ui32HistoryIndex = 0;
+#endif
+
+	/*
+		Note:
+		PDumping here means that we PDump syncs that we might not
+		need to know about for the multi-process but this
+		unavoidable as there is no point where we can PDump
+		that guarantees it will be initialised before we us it
+		(e.g. kick time is too late as the client might have
+		issued a POL on it before that point)
+	*/
+#if defined(PDUMP)
+	PDUMPCOMMENTWITHFLAGS(
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+						  PDUMP_FLAGS_PERSISTENT,
+#else
+						  PDUMP_FLAGS_CONTINUOUS,
+#endif
+						  "Allocating kernel sync object");
+	PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
+			psKernelSyncInfo->psSyncDataMemInfoKM,
+			0,
+			(IMG_UINT32)psKernelSyncInfo->psSyncDataMemInfoKM->uAllocSize,
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+			PDUMP_FLAGS_PERSISTENT,
+#else
+			PDUMP_FLAGS_CONTINUOUS,
+#endif
+			MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+	psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+	psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+	psKernelSyncInfo->sReadOps2CompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOps2Complete);
+	psKernelSyncInfo->ui32UID = g_ui32SyncUID++;
+
+	/* syncinfo meminfo has no syncinfo! */
+	psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
+
+	OSAtomicInc(psKernelSyncInfo->pvRefCount);
+
+	/* Add the SyncInfo to a global list */
+	List_PVRSRV_KERNEL_SYNC_INFO_Insert(&g_psSyncInfoList, psKernelSyncInfo);
+
+	/* return result */
+	*ppsKernelSyncInfo = psKernelSyncInfo;
+
+	return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_VOID PVRSRVAcquireSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+	OSAtomicInc(psKernelSyncInfo->pvRefCount);
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVFreeSyncInfoKM
+
+ @Description
+
+ Frees a sync info
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVReleaseSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO	*psKernelSyncInfo)
+{
+	if (OSAtomicDecAndTest(psKernelSyncInfo->pvRefCount))
+	{
+		/* Remove the SyncInfo to a global list */
+		List_PVRSRV_KERNEL_SYNC_INFO_Remove(psKernelSyncInfo);
+
+		#if defined(PDUMP)
+		PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Wait for write ops to flush to PDump value (%d)",
+								psKernelSyncInfo->psSyncData->ui32LastOpDumpVal);
+		PDUMPMEMPOL(psKernelSyncInfo->psSyncDataMemInfoKM,
+					offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+					psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
+					0xffffffff,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					PDUMP_FLAGS_CONTINUOUS,
+					MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+		PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Wait for read ops to flush to PDump value (%d)",
+								psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal);
+		PDUMPMEMPOL(psKernelSyncInfo->psSyncDataMemInfoKM,
+					offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+					psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					0xffffffff,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					PDUMP_FLAGS_CONTINUOUS,
+					MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+		#endif
+
+		FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+
+		/* Catch anyone who is trying to access the freed structure */
+		psKernelSyncInfo->psSyncDataMemInfoKM = IMG_NULL;
+		psKernelSyncInfo->psSyncData = IMG_NULL;
+		OSAtomicFree(psKernelSyncInfo->pvRefCount);
+		(IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	freeExternal
+
+ @Description
+
+ Code for freeing meminfo elements that are specific to external types memory
+
+ @Input	   psMemInfo : Kernel meminfo
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+
+static IMG_VOID freeExternal(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+	/* free the page addr array if req'd */
+	if(psMemInfo->sMemBlk.psIntSysPAddr)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+		psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+	}
+
+	/* Mem type dependent stuff */
+	if (psMemInfo->memType == PVRSRV_MEMTYPE_WRAPPED)
+	{
+		if(hOSWrapMem)
+		{
+			OSReleasePhysPageAddr(hOSWrapMem);
+		}
+	}
+#if defined(SUPPORT_ION)
+	else if (psMemInfo->memType == PVRSRV_MEMTYPE_ION)
+	{
+		if (hOSWrapMem)
+		{
+			IonUnimportBufferAndReleasePhysAddr(hOSWrapMem);
+		}
+	}
+#endif
+#if defined(SUPPORT_DMABUF)
+	else if (psMemInfo->memType == PVRSRV_MEMTYPE_DMABUF)
+	{
+		if (hOSWrapMem)
+		{
+			DmaBufUnimportAndReleasePhysAddr(hOSWrapMem);
+		}
+	}
+#endif
+}
+
+/*!
+******************************************************************************
+
+ @Function	FreeMemCallBackCommon
+
+ @Description
+
+ Common code for freeing device mem (called for freeing, unwrapping and unmapping)
+
+ @Input	   psMemInfo : Kernel meminfo
+ @Input	   ui32Param :  packet size
+ @Input	   uibFromAllocatorParam :  Are we being called by the original allocator?
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								   IMG_UINT32	ui32Param,
+								   PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	PVRSRV_MEM_TRACK_INFO  *psMemTrackInfo;
+#endif
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	/* decrement the refcount */
+	PVRSRVKernelMemInfoDecRef(psMemInfo);
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_MEM_TRACK_INFO), 
+						(IMG_VOID **)&psMemTrackInfo, IMG_NULL,
+						"Mem tracking info");
+	if (eError != PVRSRV_OK)
+		return eError;
+	psMemTrackInfo->sDevVAddr = psMemInfo->sDevVAddr;
+	psMemTrackInfo->uSize     = psMemInfo->uAllocSize;
+	psMemTrackInfo->ui32Pid = OSGetCurrentProcessIDKM();
+	psMemTrackInfo->ui32RefCount = psMemInfo->ui32RefCount;
+	psMemTrackInfo->eOp = PVRSRV_MEMTYPE_FREE;
+	psMemTrackInfo->ui32TimeStampUSecs = OSGetCurrentTimeInUSecsKM();
+
+	OSGetCurrentProcessNameKM(psMemTrackInfo->asTaskName, 128);
+
+	OSStringCopy(psMemTrackInfo->heapId, psMemInfo->heapId);
+	PVRSRVAddMemTrackInfo(psMemTrackInfo);
+#endif
+
+	/* check no other processes has this meminfo mapped */
+	if (psMemInfo->ui32RefCount == 0)
+	{
+		if((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) != 0)
+		{
+			IMG_HANDLE hMemInfo = IMG_NULL;
+
+			/* find the handle */
+			eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+									 &hMemInfo,
+									 psMemInfo,
+									 PVRSRV_HANDLE_TYPE_MEM_INFO);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+				return eError;
+			}
+
+			/* release the handle */
+			eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+										hMemInfo,
+										PVRSRV_HANDLE_TYPE_MEM_INFO);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+				return eError;
+			}
+		}
+
+		switch(psMemInfo->memType)
+		{
+			/* Fall through: Free only what we should for each memory type */
+			case PVRSRV_MEMTYPE_WRAPPED:
+			case PVRSRV_MEMTYPE_ION:
+			case PVRSRV_MEMTYPE_DMABUF:
+				freeExternal(psMemInfo);
+				// Fallthrough.
+				/* __attribute__((fallthrough)); works as well  */
+			case PVRSRV_MEMTYPE_DEVICE:
+			case PVRSRV_MEMTYPE_DEVICECLASS:
+#if defined(SUPPORT_ION)
+				if (psMemInfo->hIonSyncInfo)
+				{
+					/*
+						For syncs attached to Ion imported buffers we handle
+						things a little differently
+					*/
+					PVRSRVIonBufferSyncInfoDecRef(psMemInfo->hIonSyncInfo, psMemInfo);
+				}
+				else
+#endif
+#if defined(SUPPORT_DMABUF)
+				if (psMemInfo->hDmaBufSyncInfo)
+				{
+					PVRSRVDmaBufSyncInfoDecRef(psMemInfo->hDmaBufSyncInfo, psMemInfo);
+				}
+				else
+#endif
+				{
+					if (psMemInfo->psKernelSyncInfo)
+					{
+						PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+					}
+				}
+				break;
+			default:
+				PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
+				eError = PVRSRV_ERROR_INVALID_MEMINFO;
+		}
+	}
+
+	/*
+	 * FreeDeviceMem2 will do the right thing, freeing
+	 * the virtual memory info when the allocator calls
+	 * but only releaseing the physical pages when everyone
+	 * is done.
+	 */
+
+	if (eError == PVRSRV_OK)
+	{
+		eError = FreeDeviceMem2(psMemInfo, eCallbackOrigin);
+	}
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	FreeDeviceMemCallBack
+
+ @Description
+
+ ResMan call back to free device memory
+
+ @Input	   pvParam : data packet
+ @Input	   ui32Param :  packet size
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID  pvParam,
+										  IMG_UINT32 ui32Param,
+										  IMG_BOOL   bDummy)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+	
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param,
+								 PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVFreeDeviceMemKM
+
+ @Description
+
+ Frees memory allocated with PVRAllocDeviceMem, including the mem_info structure
+
+ @Input	   psMemInfo :
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE				hDevCookie,
+												PVRSRV_KERNEL_MEM_INFO	*psMemInfo)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (psMemInfo->sMemBlk.hResItem != IMG_NULL)
+	{
+		eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+	}
+	else
+	{
+		/* PVRSRV_MEM_NO_RESMAN */
+		eError = FreeDeviceMemCallBack(psMemInfo, 0, CLEANUP_WITH_POLL);
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAllocDeviceMemKM
+
+ @Description
+
+ Allocates device memory
+
+ @Input	   hDevCookie :
+ @Input	   psPerProc : Per-process data
+ @Input	   hDevMemHeap
+ @Input	   ui32Flags : Some combination of PVRSRV_MEM_ flags
+ @Input	   ui32Size :  Number of bytes to allocate
+ @Input	   ui32Alignment :
+ @Output   **ppsMemInfo : On success, receives a pointer to the created MEM_INFO structure
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE				hDevCookie,
+												  PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												  IMG_HANDLE				hDevMemHeap,
+												  IMG_UINT32				ui32Flags,
+												  IMG_SIZE_T				ui32Size,
+												  IMG_SIZE_T				ui32Alignment,
+												  IMG_PVOID					pvPrivData,
+												  IMG_UINT32				ui32PrivDataLength,
+												  IMG_UINT32				ui32ChunkSize,
+												  IMG_UINT32				ui32NumVirtChunks,
+												  IMG_UINT32				ui32NumPhysChunks,
+												  IMG_BOOL					*pabMapChunk,
+												  PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo;
+	PVRSRV_ERROR 			eError;
+	BM_HEAP					*psBMHeap;
+	IMG_HANDLE				hDevMemContext;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	PVRSRV_MEM_TRACK_INFO  *psMemTrackInfo;
+	IMG_UINT32 i;
+	IMG_CHAR 				*pszName = "Heap not found";
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+#endif
+
+	if (!hDevMemHeap ||
+		((ui32Size == 0) && ((ui32Flags & PVRSRV_MEM_SPARSE) == 0)) ||
+		(((ui32ChunkSize == 0) || (ui32NumVirtChunks == 0) || (ui32NumPhysChunks == 0) ||
+		(pabMapChunk == IMG_NULL )) && (ui32Flags & PVRSRV_MEM_SPARSE)))
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Sprase alloc input validation */
+	if (ui32Flags & PVRSRV_MEM_SPARSE)
+	{
+		IMG_UINT32 i;
+		IMG_UINT32 ui32Check = 0;
+
+		if (ui32NumVirtChunks < ui32NumPhysChunks)
+		{
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		for (i=0;i<ui32NumVirtChunks;i++)
+		{
+			if (pabMapChunk[i])
+			{
+				ui32Check++;
+			}
+		}
+		if (ui32NumPhysChunks != ui32Check)
+		{
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+	}
+
+	/* FIXME: At the moment we force CACHETYPE override allocations to
+	 *        be multiples of PAGE_SIZE and page aligned. If the RA/BM
+	 *        is fixed, this limitation can be removed.
+	 *
+	 * INTEGRATION_POINT: HOST_PAGESIZE() is not correct, should be device-specific.
+	 */
+	if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+	{
+		/* PRQA S 3415 1 */ /* order of evaluation is not important */
+		if (((ui32Size % HOST_PAGESIZE()) != 0) ||
+			((ui32Alignment % HOST_PAGESIZE()) != 0))
+		{
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+	}
+
+	eError = AllocDeviceMem(hDevCookie,
+							hDevMemHeap,
+							ui32Flags,
+							ui32Size,
+							ui32Alignment,
+							pvPrivData,
+							ui32PrivDataLength,
+							ui32ChunkSize,
+							ui32NumVirtChunks,
+							ui32NumPhysChunks,
+							pabMapChunk,
+							&psMemInfo);
+
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+	{
+		psMemInfo->psKernelSyncInfo = IMG_NULL;
+	}
+	else
+	{
+		/*
+			allocate a syncinfo but don't register with resman
+			because the holding devicemem will handle the syncinfo
+		*/
+		psBMHeap = (BM_HEAP*)hDevMemHeap;
+		hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+		eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+									   hDevMemContext,
+									   &psMemInfo->psKernelSyncInfo);
+		if(eError != PVRSRV_OK)
+		{
+			goto free_mainalloc;
+		}
+	}
+#if defined (MEM_TRACK_INFO_DEBUG)
+	psBMHeap = (BM_HEAP*)hDevMemHeap;
+	hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+	psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+	for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+        	if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+	        {
+    			pszName = psDeviceMemoryHeap[i].pszName;
+	        	break;
+        	}
+    	}
+
+	OSStringCopy(psMemInfo->heapId, pszName);
+#endif
+	/*
+	 * Setup the output.
+	 */
+	*ppsMemInfo = psMemInfo;
+
+	if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
+	{
+		psMemInfo->sMemBlk.hResItem = IMG_NULL;
+	}
+	else
+	{
+		/* register with the resman */
+		psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+														RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+														psMemInfo,
+														0,
+														&FreeDeviceMemCallBack);
+		if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto free_mainalloc;
+		}
+	}
+
+	/* increment the refcount */
+	PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_MEM_TRACK_INFO), 
+						(IMG_VOID **)&psMemTrackInfo, IMG_NULL,
+						"Mem tracking info");
+	if (eError != PVRSRV_OK)
+		return eError;
+	psMemTrackInfo->sDevVAddr = psMemInfo->sDevVAddr;
+	psMemTrackInfo->uSize     = psMemInfo->uAllocSize;
+	psMemTrackInfo->ui32Pid = OSGetCurrentProcessIDKM();
+	psMemTrackInfo->ui32RefCount = psMemInfo->ui32RefCount;
+	psMemTrackInfo->eOp = PVRSRV_MEMTYPE_ALLOC;
+	psMemTrackInfo->ui32TimeStampUSecs = OSGetCurrentTimeInUSecsKM();
+
+	OSGetCurrentProcessNameKM(psMemTrackInfo->asTaskName, 128);
+
+	OSStringCopy(psMemTrackInfo->heapId, psMemInfo->heapId);
+	
+	PVRSRVAddMemTrackInfo(psMemTrackInfo);
+#endif
+	/*
+	 * And I think we're done for now....
+	 */
+	return (PVRSRV_OK);
+
+free_mainalloc:
+	if (psMemInfo->psKernelSyncInfo)
+	{
+		PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+	}
+	FreeDeviceMem(psMemInfo);
+
+	return eError;
+}
+
+#if defined(SUPPORT_ION)
+static PVRSRV_ERROR IonUnmapCallback(IMG_PVOID  pvParam,
+									 IMG_UINT32 ui32Param,
+									 IMG_BOOL   bDummy)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+	
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param, PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+PVRSRV_ERROR PVRSRVIonBufferSyncAcquire(IMG_HANDLE hUnique,
+										IMG_HANDLE hDevCookie,
+										IMG_HANDLE hDevMemContext,
+										PVRSRV_ION_SYNC_INFO **ppsIonSyncInfo)
+{
+	PVRSRV_ION_SYNC_INFO *psIonSyncInfo;
+	PVRSRV_ERROR eError;
+	IMG_BOOL bRet;
+
+	/* Check the hash to see if we already have a sync for this buffer */
+	psIonSyncInfo = (PVRSRV_ION_SYNC_INFO *) HASH_Retrieve(g_psIonSyncHash, (IMG_UINTPTR_T) hUnique);
+	if (psIonSyncInfo == 0)
+	{
+		/* This buffer is new to us, create the syncinfo for it */
+		eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+							sizeof(PVRSRV_ION_SYNC_INFO),
+							(IMG_VOID **)&psIonSyncInfo, IMG_NULL,
+							"Ion Synchronization Info");
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+
+		eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+									   hDevMemContext,
+									   &psIonSyncInfo->psSyncInfo);
+		if (eError != PVRSRV_OK)
+		{
+			OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+					  sizeof(PVRSRV_ION_SYNC_INFO),
+					  psIonSyncInfo,
+					  IMG_NULL);
+
+			return eError;
+		}
+#if defined(SUPPORT_MEMINFO_IDS)
+		psIonSyncInfo->ui64Stamp = ++g_ui64MemInfoID;
+#else
+		psIonSyncInfo->ui64Stamp = 0;
+#endif
+		bRet = HASH_Insert(g_psIonSyncHash, (IMG_UINTPTR_T) hUnique, (IMG_UINTPTR_T) psIonSyncInfo);
+		if (!bRet)
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+			PVRSRVKernelSyncInfoDecRef(psIonSyncInfo->psSyncInfo, IMG_NULL);
+			OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+					  sizeof(PVRSRV_ION_SYNC_INFO),
+					  psIonSyncInfo,
+					  IMG_NULL);
+
+			return eError;
+		}
+
+		psIonSyncInfo->ui32RefCount = 0;
+		psIonSyncInfo->hUnique = hUnique;
+	}
+
+	psIonSyncInfo->ui32RefCount++;
+	*ppsIonSyncInfo = psIonSyncInfo;
+	return PVRSRV_OK;
+}
+
+IMG_VOID PVRSRVIonBufferSyncRelease(PVRSRV_ION_SYNC_INFO *psIonSyncInfo)
+{
+	psIonSyncInfo->ui32RefCount--;
+
+	if (psIonSyncInfo->ui32RefCount == 0)
+	{
+		PVRSRV_ION_SYNC_INFO *psLookup;
+		/*
+			If we're holding the last reference to the syncinfo
+			then free it
+		*/
+		psLookup = (PVRSRV_ION_SYNC_INFO *) HASH_Remove(g_psIonSyncHash, (IMG_UINTPTR_T) psIonSyncInfo->hUnique);
+		PVR_ASSERT(psLookup == psIonSyncInfo);
+		PVRSRVKernelSyncInfoDecRef(psIonSyncInfo->psSyncInfo, IMG_NULL);
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+				  sizeof(PVRSRV_ION_SYNC_INFO),
+				  psIonSyncInfo,
+				  IMG_NULL);
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVMapIonHandleKM
+
+ @Description
+
+ Map an ION buffer into the specified device memory context
+
+ @Input	   psPerProc : PerProcess data
+ @Input    hDevCookie : Device node cookie
+ @Input    hDevMemHeap : Heap ion handles are mapped into
+ @Input    ui32NumBuffers : Number of ion handles to map. (If one handle is being
+                            mapped, this should be 1, not 0.)
+ @Input    phIon : Array of ui32NumBuffers ion handles (fds)
+ @Input    ui32Flags : Mapping flags
+ @Input    ui32ChunkCount : If ui32NumBuffers is 1, this is the number of
+                            "chunks" specified to be mapped into device-virtual
+                            address space. If ui32NumBuffers > 1, it is ignored.
+ @Input    pauiOffset : Array of offsets in device-virtual address space to map
+                        "chunks" of physical from the ion allocation.
+ @Input    pauiSize : Array of sizes in bytes of device-virtual address space to
+                      map "chunks" of physical from the ion allocation.
+ @Input    puiIonBufferSize : Size in bytes of resulting device-virtual mapping.
+ @Output   ppsKernelMemInfo: Output kernel meminfo if successful
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVMapIonHandleKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+								  IMG_HANDLE hDevCookie,
+								  IMG_HANDLE hDevMemHeap,
+								  IMG_UINT32 ui32NumFDs,
+								  IMG_INT32  *pi32BufferFDs,
+								  IMG_UINT32 ui32Flags,
+								  IMG_UINT32 ui32ChunkCount,
+								  IMG_SIZE_T *pauiOffset,
+								  IMG_SIZE_T *pauiSize,
+								  IMG_SIZE_T *puiIonBufferSize,
+								  PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo,
+								  IMG_UINT64 *pui64Stamp)
+{
+	PVRSRV_ENV_PER_PROCESS_DATA *psPerProcEnv = PVRSRVProcessPrivateData(psPerProc);
+	PVRSRV_DEVICE_NODE *psDeviceNode; 
+	PVRSRV_KERNEL_MEM_INFO *psNewKernelMemInfo;
+	IMG_SYS_PHYADDR *pasSysPhysAddr;
+	IMG_SYS_PHYADDR *pasAdjustedSysPhysAddr;
+	PVRSRV_MEMBLK *psMemBlock;
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hPriv;
+	IMG_HANDLE hUnique;
+	BM_HANDLE hBuffer;
+	IMG_SIZE_T uiMapSize = 0;
+	IMG_SIZE_T uiAdjustOffset = 0;
+	IMG_UINT32 ui32PageCount;
+	IMG_UINT32 i;
+	IMG_BOOL bAllocSync = (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)?IMG_FALSE:IMG_TRUE;
+
+	if ((hDevCookie == IMG_NULL) || (ui32ChunkCount == 0)
+		 || (hDevMemHeap == IMG_NULL) || (ppsKernelMemInfo == IMG_NULL)
+		 || (psPerProcEnv == IMG_NULL))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid params", __FUNCTION__));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	for (i=0;i<ui32ChunkCount;i++)
+	{
+		if ((pauiOffset[i] & HOST_PAGEMASK) != 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"%s: Chunk offset is not page aligned", __FUNCTION__));
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		if ((pauiSize[i] & HOST_PAGEMASK) != 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"%s: Chunk size is not page aligned", __FUNCTION__));
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+		uiMapSize += pauiSize[i];
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psNewKernelMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to alloc memory for block", __FUNCTION__));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet(psNewKernelMemInfo, 0, sizeof(PVRSRV_KERNEL_MEM_INFO));
+
+	/* Import the ION buffer into our ion_client and DMA map it */
+	eError = IonImportBufferAndAcquirePhysAddr(psPerProcEnv->psIONClient,
+											   ui32NumFDs,
+											   pi32BufferFDs,
+											   &ui32PageCount,
+											   &pasSysPhysAddr,
+											   &psNewKernelMemInfo->pvLinAddrKM,
+											   &hPriv,
+											   &hUnique);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get ion buffer/buffer phys addr", __FUNCTION__));
+		goto exitFailedImport;
+	}
+
+	/*
+		Make sure the number of pages detected by the ion import are at least
+		the size of the total chunked region
+	*/
+	if(ui32PageCount * PAGE_SIZE < uiMapSize)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: ion allocator returned fewer page addresses "
+								"than specified chunk size(s)", __FUNCTION__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto exitFailedAdjustedAlloc; 
+	}
+
+	/*
+		An Ion buffer might have a number of "chunks" in it which need to be
+		mapped virtually continuous so we need to create a new array of
+		addresses based on this chunk data for the actual wrap
+	*/
+	/* OSAllocMem() must be provided non-zero value for size argument */
+    	PVR_ASSERT(sizeof(IMG_SYS_PHYADDR) * (uiMapSize/HOST_PAGESIZE() != 0));
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(IMG_SYS_PHYADDR) * (uiMapSize/HOST_PAGESIZE()),
+					(IMG_VOID **)&pasAdjustedSysPhysAddr, IMG_NULL,
+					"Ion adjusted system address array") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to alloc memory for adjusted array", __FUNCTION__));
+		goto exitFailedAdjustedAlloc;
+	}
+	OSMemSet(pasAdjustedSysPhysAddr, 0, sizeof(IMG_SYS_PHYADDR) * (uiMapSize/HOST_PAGESIZE()));
+
+	for (i=0;i<ui32ChunkCount;i++)
+	{
+		OSMemCopy(&pasAdjustedSysPhysAddr[uiAdjustOffset],
+				  &pasSysPhysAddr[pauiOffset[i]/HOST_PAGESIZE()],
+				  (pauiSize[i]/HOST_PAGESIZE()) * sizeof(IMG_SYS_PHYADDR));
+
+		uiAdjustOffset += pauiSize[i]/HOST_PAGESIZE();
+	}
+
+	/* Wrap the returned addresses into our memory context */
+	if (!BM_Wrap(hDevMemHeap,
+				 uiMapSize,
+				 0,
+				 IMG_FALSE,
+				 pasAdjustedSysPhysAddr,
+				 IMG_NULL,
+				 &ui32Flags,	/* This function clobbers our bits in ui32Flags */
+				 &hBuffer))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to wrap ion buffer", __FUNCTION__));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto exitFailedWrap;
+	}
+
+	/* Fill in "Implementation dependant" section of mem info */
+	psMemBlock = &psNewKernelMemInfo->sMemBlk;
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+	psMemBlock->hBuffer = (IMG_HANDLE) hBuffer;
+	psMemBlock->hOSWrapMem = hPriv;			/* Saves creating a new element as we know hOSWrapMem will not be used */
+	psMemBlock->psIntSysPAddr = pasAdjustedSysPhysAddr;
+
+	psNewKernelMemInfo->ui32Flags = ui32Flags;
+	psNewKernelMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	psNewKernelMemInfo->uAllocSize = uiMapSize;
+	psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_ION;
+	PVRSRVKernelMemInfoIncRef(psNewKernelMemInfo);
+
+	/* Clear the Backup buffer pointer as we do not have one at this point. We only allocate this as we are going up/down */
+	psNewKernelMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+	if (!bAllocSync)
+	{
+		psNewKernelMemInfo->psKernelSyncInfo = IMG_NULL;
+	}
+	else
+	{
+		PVRSRV_ION_SYNC_INFO *psIonSyncInfo;
+		BM_HEAP *psBMHeap;
+		IMG_HANDLE hDevMemContext;
+
+		psBMHeap = (BM_HEAP*)hDevMemHeap;
+		hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+
+		eError = PVRSRVIonBufferSyncInfoIncRef(hUnique,
+											   hDevCookie,
+											   hDevMemContext,
+											   &psIonSyncInfo,
+											   psNewKernelMemInfo);
+		if(eError != PVRSRV_OK)
+		{
+			goto exitFailedSync;
+		}
+		psNewKernelMemInfo->hIonSyncInfo = psIonSyncInfo;
+		psNewKernelMemInfo->psKernelSyncInfo = IonBufferSyncGetKernelSyncInfo(psIonSyncInfo);
+		*pui64Stamp = IonBufferSyncGetStamp(psIonSyncInfo);
+	}
+
+	/* register with the resman */
+	psNewKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+															 RESMAN_TYPE_DEVICEMEM_ION,
+															 psNewKernelMemInfo,
+															 0,
+															 &IonUnmapCallback);
+	if (psNewKernelMemInfo->sMemBlk.hResItem == IMG_NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto exitFailedResman;
+	}
+
+	psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_ION;
+
+	/*
+		As the user doesn't tell us the size, just the "chunk" information
+		return actual size of the Ion buffer so we can mmap it.
+	*/
+	*puiIonBufferSize = ui32PageCount * HOST_PAGESIZE();
+	*ppsKernelMemInfo = psNewKernelMemInfo;
+	return PVRSRV_OK;
+
+exitFailedResman:
+	if (psNewKernelMemInfo->psKernelSyncInfo)
+	{
+		PVRSRVIonBufferSyncInfoDecRef(psNewKernelMemInfo->hIonSyncInfo, psNewKernelMemInfo);
+	}
+exitFailedSync:
+	BM_Free(hBuffer, ui32Flags
+				#if defined (PVRSRV_DEVMEM_TIME_STATS)
+					, IMG_NULL
+				#endif
+				);
+exitFailedWrap:
+	OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+			  sizeof(IMG_SYS_PHYADDR) * uiAdjustOffset,
+			  pasAdjustedSysPhysAddr,
+			  IMG_NULL);
+exitFailedAdjustedAlloc:
+	IonUnimportBufferAndReleasePhysAddr(hPriv);
+exitFailedImport:
+	OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+			  sizeof(PVRSRV_KERNEL_MEM_INFO),
+			  psNewKernelMemInfo,
+			  IMG_NULL);
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVUnmapIonHandleKM
+
+ @Description
+
+ Frees an ion buffer mapped with PVRSRVMapIonHandleKM, including the mem_info structure
+
+ @Input	   psMemInfo :
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapIonHandleKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+#endif	/* SUPPORT_ION */
+
+#if defined(SUPPORT_DMABUF)
+static PVRSRV_ERROR DmaBufUnmapCallback(IMG_PVOID  pvParam,
+									 IMG_UINT32 ui32Param,
+									 IMG_BOOL   bDummy)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+	
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param, PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+PVRSRV_ERROR PVRSRVDmaBufSyncAcquire(IMG_HANDLE hUnique,
+										IMG_HANDLE hPriv,
+										IMG_HANDLE hDevCookie,
+										IMG_HANDLE hDevMemContext,
+										PVRSRV_DMABUF_SYNC_INFO **ppsDmaBufSyncInfo)
+{
+	PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo;
+	PVRSRV_ERROR eError;
+	IMG_BOOL bRet;
+
+	/*
+	 * If the import has a unique handle, check the hash to see if we
+	 * already have a sync for the buffer.
+	 */
+	psDmaBufSyncInfo = (PVRSRV_DMABUF_SYNC_INFO *) HASH_Retrieve(g_psDmaBufSyncHash, (IMG_UINTPTR_T)hUnique);
+	if (!psDmaBufSyncInfo)
+	{
+		/* Create the syncinfo for the import */
+		eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+							sizeof(PVRSRV_DMABUF_SYNC_INFO),
+							(IMG_VOID **)&psDmaBufSyncInfo, IMG_NULL,
+							"DMA-BUF Synchronization Info");
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorAllocDmaBufSyncInfo;
+		}
+
+		eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+									   hDevMemContext,
+									   &psDmaBufSyncInfo->psSyncInfo);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorAllocSyncInfo;
+		}
+#if defined(SUPPORT_MEMINFO_IDS)
+		psDmaBufSyncInfo->ui64Stamp = ++g_ui64MemInfoID;
+#else
+		psDmaBufSyncInfo->ui64Stamp = 0;
+#endif
+		psDmaBufSyncInfo->ui32RefCount = 0;
+		psDmaBufSyncInfo->hUnique = hUnique;
+
+		psDmaBufSyncInfo->psSyncInfo->hFenceContext = PVRLinuxFenceContextCreate(psDmaBufSyncInfo->psSyncInfo, hPriv);
+		if (!psDmaBufSyncInfo->psSyncInfo->hFenceContext)
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto ErrorCreateFenceContext;
+		}
+
+		bRet = HASH_Insert(g_psDmaBufSyncHash, (IMG_UINTPTR_T)hUnique, (IMG_UINTPTR_T) psDmaBufSyncInfo);
+		if (!bRet)
+		{
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto ErrorHashInsert;
+		}
+	}
+
+	psDmaBufSyncInfo->ui32RefCount++;
+	*ppsDmaBufSyncInfo = psDmaBufSyncInfo;
+	return PVRSRV_OK;
+
+ErrorHashInsert:
+	PVRLinuxFenceContextDestroy(psDmaBufSyncInfo->psSyncInfo->hFenceContext);
+ErrorCreateFenceContext:
+	PVRSRVKernelSyncInfoDecRef(psDmaBufSyncInfo->psSyncInfo, IMG_NULL);
+ErrorAllocSyncInfo:
+	OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+			  sizeof(PVRSRV_DMABUF_SYNC_INFO),
+			  psDmaBufSyncInfo,
+			  IMG_NULL);
+ErrorAllocDmaBufSyncInfo:
+	return eError;
+}
+
+IMG_VOID PVRSRVDmaBufSyncRelease(PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo)
+{
+	psDmaBufSyncInfo->ui32RefCount--;
+
+	if (psDmaBufSyncInfo->ui32RefCount == 0)
+	{
+		PVRSRV_DMABUF_SYNC_INFO *psLookup;
+
+		/*
+			If we're holding the last reference to the syncinfo
+			then free it
+		*/
+
+		psLookup = (PVRSRV_DMABUF_SYNC_INFO *) HASH_Remove(g_psDmaBufSyncHash, (IMG_UINTPTR_T) psDmaBufSyncInfo->hUnique);
+		PVR_ASSERT(psLookup == psDmaBufSyncInfo);
+		(void)psLookup;
+
+		PVRLinuxFenceContextDestroy(psDmaBufSyncInfo->psSyncInfo->hFenceContext);
+		PVRSRVKernelSyncInfoDecRef(psDmaBufSyncInfo->psSyncInfo, IMG_NULL);
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+				  sizeof(PVRSRV_DMABUF_SYNC_INFO),
+				  psDmaBufSyncInfo,
+				  IMG_NULL);
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVMapDmaBufKM
+
+ @Description
+
+ Map a dma_buf into the specified device memory context
+
+ @Input	   psPerProc : PerProcess data.
+ @Input    hDevCookie : Device node cookie.
+ @Input    hDevMemHeap : Heap the buffers are mapped into.
+ @Input    ui32Flags : Mapping flags.
+ @Input    i32DmaBufFD : DMA Buf FD.
+ @Input    uiDmaBufOffset : Offset into DMA Buf.
+ @Input    uiDmaBufSize : Size of DMA Buf chunk.
+ @Output   ppsKernelMemInfo: Output kernel meminfo if successful.
+ @Output   puiSize : Size in bytes of resulting device-virtual mapping.
+ @Output   puiMemInfoOffset : Array of offsets of each chunk in the meminfo.
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVMapDmaBufKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+								  IMG_HANDLE hDevCookie,
+								  IMG_HANDLE hDevMemHeap,
+								  IMG_UINT32 ui32Flags,
+								  IMG_INT32 i32DmaBufFD,
+								  IMG_SIZE_T uiDmaBufOffset,
+								  IMG_SIZE_T uiDmaBufSize,
+								  PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo,
+								  IMG_SIZE_T *puiSize,
+								  IMG_SIZE_T *puiMemInfoOffset,
+								  IMG_UINT64 *pui64Stamp)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode; 
+	PVRSRV_KERNEL_MEM_INFO *psNewKernelMemInfo;
+	IMG_SYS_PHYADDR *pasSysPhysAddr;
+	PVRSRV_MEMBLK *psMemBlock;
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hPriv;
+	IMG_HANDLE hUnique;
+	BM_HANDLE hBuffer;
+	IMG_SIZE_T uiMapSize = 0;
+	IMG_UINT32 ui32PageCount;
+	IMG_BOOL bAllocSync = (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) ? IMG_FALSE : IMG_TRUE;
+
+	if ((hDevCookie == IMG_NULL) || (hDevMemHeap == IMG_NULL)
+		|| (ppsKernelMemInfo == IMG_NULL))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid params", __FUNCTION__));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+	if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psNewKernelMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: Failed to alloc memory for block", __FUNCTION__));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet(psNewKernelMemInfo, 0, sizeof(PVRSRV_KERNEL_MEM_INFO));
+
+	/* Import the DMA Buffer */
+	eError = DmaBufImportAndAcquirePhysAddr(i32DmaBufFD,
+											uiDmaBufOffset,
+											uiDmaBufSize,
+											&ui32PageCount,
+											&pasSysPhysAddr,
+											puiMemInfoOffset,
+											&psNewKernelMemInfo->pvLinAddrKM,
+											&hPriv,
+											&hUnique);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get dma-buf phys addr", __FUNCTION__));
+		goto exitFailedImport;
+	}
+
+	uiMapSize = ui32PageCount * HOST_PAGESIZE();
+
+	/* Wrap the returned addresses into our memory context */
+	if (!BM_Wrap(hDevMemHeap,
+				 uiMapSize,
+				 0,
+				 IMG_FALSE,
+				 pasSysPhysAddr,
+				 IMG_NULL,
+				 &ui32Flags,	/* This function clobbers our bits in ui32Flags */
+				 &hBuffer))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to wrap dma-buf", __FUNCTION__));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto exitFailedWrap;
+	}
+
+	/* Fill in "Implementation dependant" section of mem info */
+	psMemBlock = &psNewKernelMemInfo->sMemBlk;
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+	psMemBlock->hBuffer = (IMG_HANDLE) hBuffer;
+	psMemBlock->hOSWrapMem = hPriv;			/* Saves creating a new element as we know hOSWrapMem will not be used */
+	psMemBlock->psIntSysPAddr = pasSysPhysAddr;
+
+	psNewKernelMemInfo->ui32Flags = ui32Flags;
+	psNewKernelMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	psNewKernelMemInfo->uAllocSize = uiMapSize;
+	psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_DMABUF;
+	PVRSRVKernelMemInfoIncRef(psNewKernelMemInfo);
+
+	if (!bAllocSync)
+	{
+		psNewKernelMemInfo->psKernelSyncInfo = IMG_NULL;
+	}
+	else
+	{
+		PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo;
+		BM_HEAP *psBMHeap;
+		IMG_HANDLE hDevMemContext;
+
+		psBMHeap = (BM_HEAP*)hDevMemHeap;
+		hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+
+		eError = PVRSRVDmaBufSyncInfoIncRef(hUnique,
+											   hPriv,
+											   hDevCookie,
+											   hDevMemContext,
+											   &psDmaBufSyncInfo,
+											   psNewKernelMemInfo);
+		if(eError != PVRSRV_OK)
+		{
+			goto exitFailedSync;
+		}
+		psNewKernelMemInfo->hDmaBufSyncInfo = psDmaBufSyncInfo;
+		psNewKernelMemInfo->psKernelSyncInfo = psDmaBufSyncInfo->psSyncInfo;
+		*pui64Stamp = DmaBufSyncGetStamp(psDmaBufSyncInfo);
+	}
+
+	/* register with the resman */
+	psNewKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+															 RESMAN_TYPE_DEVICEMEM_DMABUF,
+															 psNewKernelMemInfo,
+															 0,
+															 &DmaBufUnmapCallback);
+	if (psNewKernelMemInfo->sMemBlk.hResItem == IMG_NULL)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto exitFailedResman;
+	}
+
+	psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_DMABUF;
+
+	/* Return actual size of the imported memory so we can mmap it */
+	*puiSize = uiMapSize;
+	*ppsKernelMemInfo = psNewKernelMemInfo;
+	return PVRSRV_OK;
+
+exitFailedResman:
+	if (psNewKernelMemInfo->psKernelSyncInfo)
+	{
+		PVRSRVDmaBufSyncInfoDecRef(psNewKernelMemInfo->hDmaBufSyncInfo, psNewKernelMemInfo);
+	}
+exitFailedSync:
+	BM_Free(hBuffer, ui32Flags
+				#if defined (PVRSRV_DEVMEM_TIME_STATS)
+					, IMG_NULL
+				#endif
+				);
+
+exitFailedWrap:
+	DmaBufUnimportAndReleasePhysAddr(hPriv);
+exitFailedImport:
+	OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+			  sizeof(PVRSRV_KERNEL_MEM_INFO),
+			  psNewKernelMemInfo,
+			  IMG_NULL);
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVUnmapDmaBufKM
+
+ @Description
+
+ Releases a dma_buf mapped with PVRSRVMapDmaBufKM, including the mem_info structure
+
+ @Input	   psMemInfo :
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDmaBufKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+#endif	/* SUPPORT_DMABUF */
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDissociateDeviceMemKM
+
+ @Description
+
+ Dissociates memory from the process that allocates it.  Intended for
+ transfering the ownership of device memory from a particular process
+ to the kernel.
+
+ @Input	   psMemInfo :
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE              hDevCookie,
+													  PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevCookie;
+
+	PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem, psDeviceNode->hResManContext);
+
+	PVR_ASSERT(eError == PVRSRV_OK);
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetFreeDeviceMemKM
+
+ @Description
+
+ Determines how much memory remains available in the system with the specified
+ capabilities.
+
+ @Input	   ui32Flags :
+
+ @Output   pui32Total :
+
+ @Output   pui32Free :
+
+ @Output   pui32LargestBlock :
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+												   IMG_SIZE_T *pui32Total,
+												   IMG_SIZE_T *pui32Free,
+												   IMG_SIZE_T *pui32LargestBlock)
+{
+	/* TO BE IMPLEMENTED */
+
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(pui32Total);
+	PVR_UNREFERENCED_PARAMETER(pui32Free);
+	PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
+
+	return PVRSRV_OK;
+}
+
+
+
+
+/*!
+******************************************************************************
+	@Function   PVRSRVUnwrapExtMemoryKM
+
+	@Description  On last unwrap of a given meminfo, unmaps physical pages from a
+				wrapped allocation, and frees the associated device address space.
+				Note: this can only unmap memory mapped by PVRSRVWrapExtMemory
+
+	@Input	    psMemInfo - mem info describing the wrapped allocation
+	@Return     None
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO	*psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+
+
+/*!
+******************************************************************************
+	@Function   UnwrapExtMemoryCallBack
+
+	@Description Resman callback to unwrap memory
+
+	@Input	    pvParam - opaque void ptr param
+	@Input	    ui32Param - opaque unsigned long param
+	@Return     PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID  pvParam,
+											IMG_UINT32 ui32Param,
+											IMG_BOOL   bDummy)
+{
+	PVRSRV_KERNEL_MEM_INFO	*psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+	
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param,
+								 PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+
+/*!
+******************************************************************************
+	@Function   PVRSRVWrapExtMemoryKM
+
+	@Description  Allocates a Device Virtual Address in the shared mapping heap
+				and maps physical pages into that allocation. Note, if the pages are
+				already mapped into the heap, the existing allocation is returned.
+
+	@Input	    hDevCookie - Device cookie
+	@Input	    psPerProc - Per-process data
+	@Input	    hDevMemContext - device memory context
+	@Input	    uByteSize - Size of allocation
+	@Input	    uPageOffset - Offset into the first page of the memory to be wrapped
+	@Input	    bPhysContig - whether the underlying memory is physically contiguous
+	@Input	    psExtSysPAddr - The list of Device Physical page addresses
+	@Input	    pvLinAddr - ptr to buffer to wrap
+	@Output     ppsMemInfo - mem info describing the wrapped allocation
+	@Return     None
+******************************************************************************/
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE				hDevCookie,
+												PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												IMG_HANDLE				hDevMemContext,
+												IMG_SIZE_T 				uByteSize,
+												IMG_SIZE_T				uPageOffset,
+												IMG_BOOL				bPhysContig,
+												IMG_SYS_PHYADDR	 		*psExtSysPAddr,
+												IMG_VOID 				*pvLinAddr,
+												IMG_UINT32				ui32Flags,
+												PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo)
+{
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+	DEVICE_MEMORY_INFO  *psDevMemoryInfo;
+	IMG_SIZE_T			ui32HostPageSize = HOST_PAGESIZE();
+	IMG_HANDLE			hDevMemHeap = IMG_NULL;
+	PVRSRV_DEVICE_NODE* psDeviceNode;
+	BM_HANDLE 			hBuffer;
+	PVRSRV_MEMBLK		*psMemBlock;
+	IMG_BOOL			bBMError;
+	BM_HEAP				*psBMHeap;
+	PVRSRV_ERROR		eError;
+	IMG_VOID 			*pvPageAlignedCPUVAddr;
+	IMG_SYS_PHYADDR	 	*psIntSysPAddr = IMG_NULL;
+	IMG_HANDLE			hOSWrapMem = IMG_NULL;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;IMG_UINT32		i;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	PVRSRV_MEM_TRACK_INFO  *psMemTrackInfo;
+	IMG_CHAR 			*pszName="Heap not found";
+#endif
+	IMG_SIZE_T          uPageCount = 0;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"PVRSRVWrapExtMemoryKM (uSize=0x%" SIZE_T_FMT_LEN "x, uPageOffset=0x%"
+			SIZE_T_FMT_LEN "x, bPhysContig=%d, extSysPAddr=" SYSPADDR_FMT
+			", pvLinAddr=%p, ui32Flags=%u)",
+			uByteSize,
+			uPageOffset,
+			bPhysContig,
+			psExtSysPAddr?psExtSysPAddr->uiAddr:0x0,
+			pvLinAddr,
+			ui32Flags));
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
+	PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+	if (psDeviceNode == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if(pvLinAddr)
+	{
+		/* derive the page offset from the cpu ptr (in case it's not supplied) */
+		uPageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
+
+		/* get the pagecount and the page aligned base ptr */
+		uPageCount = HOST_PAGEALIGN(uByteSize + uPageOffset) / ui32HostPageSize;
+		pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - uPageOffset);
+
+		/* allocate array of SysPAddr to hold page addresses */
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						uPageCount * sizeof(IMG_SYS_PHYADDR),
+						(IMG_VOID **)&psIntSysPAddr, IMG_NULL,
+						"Array of Page Addresses") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+		eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+										uPageCount * ui32HostPageSize,
+										psIntSysPAddr,
+										&hOSWrapMem);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;//FIXME: need better error code
+			goto ErrorExitPhase1;
+		}
+
+		/* replace the supplied page address list */
+		psExtSysPAddr = psIntSysPAddr;
+
+		/* assume memory is not physically contiguous;
+  		   we shouldn't trust what the user says here
+  		*/
+		bPhysContig = IMG_FALSE;
+	}
+#if !defined(__QNXNTO__)
+	else
+	{
+		if (psExtSysPAddr)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter, physical address passing is not supported"));
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter, no address specified"));
+		}
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+#endif
+
+
+	/* Choose the heap to map to */
+	psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+	for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+		{
+			if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+			{
+				if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+				{
+					hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+				#if defined (MEM_TRACK_INFO_DEBUG)
+					pszName = psDeviceMemoryHeap[i].pszName;
+				#endif
+				}
+				else
+				{
+					hDevMemHeap = IMG_NULL;
+				}
+			}
+			else
+			{
+				hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+			#if defined (MEM_TRACK_INFO_DEBUG)
+				pszName = psDeviceMemoryHeap[i].pszName;
+			#endif
+			}
+			break;
+		}
+	}
+
+	if(hDevMemHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: unable to find mapping heap"));
+		eError = PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP;
+		goto ErrorExitPhase2;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExitPhase2;
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+	/*
+		Force the memory to be read/write. This used to be done in the BM, but
+		ion imports don't want this behaviour
+	*/
+	psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE;
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+	bBMError = BM_Wrap(hDevMemHeap,
+					   uByteSize,
+					   uPageOffset,
+					   bPhysContig,
+					   psExtSysPAddr,
+					   IMG_NULL,
+					   &psMemInfo->ui32Flags,
+					   &hBuffer);
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto ErrorExitPhase3;
+	}
+
+	/* Fill in "Implementation dependant" section of mem info */
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+	psMemBlock->hOSWrapMem = hOSWrapMem;
+	psMemBlock->psIntSysPAddr = psIntSysPAddr;
+
+	/* Convert from BM_HANDLE to external IMG_HANDLE */
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+	/* Fill in the public fields of the MEM_INFO structure */
+	psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	psMemInfo->uAllocSize = uByteSize;
+
+	/* Clear the Backup buffer pointer as we do not have one at this point.
+	   We only allocate this as we are going up/down
+	 */
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+	/*
+		allocate a syncinfo but don't register with resman
+		because the holding devicemem will handle the syncinfo
+	*/
+	psBMHeap = (BM_HEAP*)hDevMemHeap;
+	hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+	eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+									hDevMemContext,
+									&psMemInfo->psKernelSyncInfo);
+	if(eError != PVRSRV_OK)
+	{
+		FreeDeviceMem(psMemInfo);
+		/*  FreeDeviceMem will free the meminfo so jump straight to ErrorExitPhase2 */
+		goto ErrorExitPhase2;
+	}
+
+	/* increment the refcount */
+	PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
+
+	/* Register Resource */
+	psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													RESMAN_TYPE_DEVICEMEM_WRAP,
+													psMemInfo,
+													0,
+													&UnwrapExtMemoryCallBack);
+#if defined (MEM_TRACK_INFO_DEBUG)
+	OSStringCopy(psMemInfo->heapId, pszName);
+#endif
+	/* return the meminfo */
+	*ppsMemInfo = psMemInfo;
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_MEM_TRACK_INFO), 
+						(IMG_VOID **)&psMemTrackInfo, IMG_NULL,
+						"Mem tracking info");
+	if (eError != PVRSRV_OK)
+		return eError;
+	psMemTrackInfo->sDevVAddr = psMemInfo->sDevVAddr;
+	psMemTrackInfo->uSize     = psMemInfo->uAllocSize;
+	psMemTrackInfo->ui32Pid = OSGetCurrentProcessIDKM();
+	psMemTrackInfo->ui32RefCount = psMemInfo->ui32RefCount;
+	psMemTrackInfo->eOp = PVRSRV_MEMTYPE_WRAPPED;
+	psMemTrackInfo->ui32TimeStampUSecs = OSGetCurrentTimeInUSecsKM();
+
+	OSGetCurrentProcessNameKM(psMemTrackInfo->asTaskName, 128);
+
+	OSStringCopy(psMemTrackInfo->heapId, psMemInfo->heapId);
+	PVRSRVAddMemTrackInfo(psMemTrackInfo);
+#endif
+
+	return PVRSRV_OK;
+
+	/* error handling: */
+ErrorExitPhase3:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+
+ErrorExitPhase2:
+	if(hOSWrapMem)
+	{
+		OSReleasePhysPageAddr(hOSWrapMem);
+	}
+
+ErrorExitPhase1:
+	if(psIntSysPAddr)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
+		/*not nulling shared pointer, uninitialized to this point*/
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVUnmapDeviceMemoryKM
+
+ @Description
+ 		Unmaps an existing allocation previously mapped by PVRSRVMapDeviceMemory
+
+ @Input    psMemInfo
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+
+
+/*!
+******************************************************************************
+	@Function   UnmapDeviceMemoryCallBack
+
+	@Description Resman callback to unmap memory memory previously mapped
+				from one allocation to another
+
+	@Input	    pvParam - opaque void ptr param
+	@Input	    ui32Param - opaque unsigned long param
+	@Return     PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID  pvParam,
+											  IMG_UINT32 ui32Param,
+											  IMG_BOOL   bDummy)
+{
+	PVRSRV_ERROR				eError;
+	RESMAN_MAP_DEVICE_MEM_DATA	*psMapData = pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	if(psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMapData->psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+		psMapData->psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+	}
+
+	if( psMapData->psMemInfo->psKernelSyncInfo )
+	{
+		PVRSRVKernelSyncInfoDecRef(psMapData->psMemInfo->psKernelSyncInfo, psMapData->psMemInfo);
+	}
+
+	eError = FreeDeviceMem(psMapData->psMemInfo);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free DST meminfo"));
+		return eError;
+	}
+
+	/* This will only free the src psMemInfo if we hold the last reference */
+	eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0,
+								   PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER);
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVMapDeviceMemoryKM
+
+ @Description
+ 		Maps an existing allocation to a specific device address space and heap
+ 		Note: it's valid to map from one physical device to another
+
+ @Input	   psPerProc : Per-process data
+ @Input    psSrcMemInfo
+ @Input    hDstDevMemHeap
+ @Input    ppsDstMemInfo
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+												  PVRSRV_KERNEL_MEM_INFO	*psSrcMemInfo,
+												  IMG_HANDLE				hDstDevMemHeap,
+												  PVRSRV_KERNEL_MEM_INFO	**ppsDstMemInfo)
+{
+	PVRSRV_ERROR				eError;
+	IMG_UINT32					i;
+	IMG_SIZE_T					uPageCount, uPageOffset;
+	IMG_SIZE_T					ui32HostPageSize = HOST_PAGESIZE();
+	IMG_SYS_PHYADDR				*psSysPAddr = IMG_NULL;
+	IMG_DEV_PHYADDR				sDevPAddr;
+	BM_BUF						*psBuf;
+	IMG_DEV_VIRTADDR			sDevVAddr;
+	PVRSRV_KERNEL_MEM_INFO		*psMemInfo = IMG_NULL;
+	BM_HANDLE 					hBuffer;
+	PVRSRV_MEMBLK				*psMemBlock;
+	IMG_BOOL					bBMError;
+	PVRSRV_DEVICE_NODE			*psDeviceNode;
+	IMG_VOID 					*pvPageAlignedCPUVAddr;
+	RESMAN_MAP_DEVICE_MEM_DATA	*psMapData = IMG_NULL;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	PVRSRV_MEM_TRACK_INFO  		*psMemTrackInfo;
+	DEVICE_MEMORY_INFO  		*psDevMemoryInfo;
+	DEVICE_MEMORY_HEAP_INFO 	*psDeviceMemoryHeap;
+	BM_HEAP 					*psBMHeap;
+	IMG_HANDLE  				hDevMemContext;
+#endif
+
+	/* check params */
+	if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* initialise the Dst Meminfo to NULL*/
+	*ppsDstMemInfo = IMG_NULL;
+
+	uPageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
+	uPageCount = HOST_PAGEALIGN(psSrcMemInfo->uAllocSize + uPageOffset) / ui32HostPageSize;
+	pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - uPageOffset);
+
+	/*
+		allocate array of SysPAddr to hold SRC allocation page addresses
+	*/
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					uPageCount*sizeof(IMG_SYS_PHYADDR),
+					(IMG_VOID **)&psSysPAddr, IMG_NULL,
+					"Array of Page Addresses") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psBuf = psSrcMemInfo->sMemBlk.hBuffer;
+
+	/* get the device node */
+	psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+	/* build a list of physical page addresses */
+	sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(uPageOffset);
+	for(i=0; i<uPageCount; i++)
+	{
+		BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+
+		/* save the address */
+		psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
+
+		/* advance the DevVaddr one page */
+		sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
+	}
+
+	/* allocate the resman map data */
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+					(IMG_VOID **)&psMapData, IMG_NULL,
+					"Resource Manager Map Data") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExit;
+	}
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorExit;
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+	/*
+		Force the memory to be read/write. This used to be done in the BM, but
+		ion imports don't want this behaviour
+	*/
+	psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE;
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+	bBMError = BM_Wrap(hDstDevMemHeap,
+					   psSrcMemInfo->uAllocSize,
+					   uPageOffset,
+					   IMG_FALSE,
+					   psSysPAddr,
+					   pvPageAlignedCPUVAddr,
+					   &psMemInfo->ui32Flags,
+					   &hBuffer);
+
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto ErrorExit;
+	}
+
+	/* Fill in "Implementation dependant" section of mem info */
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+	/* Convert from BM_HANDLE to external IMG_HANDLE */
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+	/* Store page list */
+	psMemBlock->psIntSysPAddr = psSysPAddr;
+
+	/* patch up the CPU VAddr into the meminfo */
+	psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
+
+	/* Fill in the public fields of the MEM_INFO structure */
+	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	psMemInfo->uAllocSize = psSrcMemInfo->uAllocSize;
+	psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
+
+	/* reference the same ksi that the original meminfo referenced */
+	if(psMemInfo->psKernelSyncInfo)
+	{
+		PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+	}
+
+	/* Clear the Backup buffer pointer as we do not have one at this point.
+	   We only allocate this as we are going up/down
+	 */
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+	/* increment our refcount */
+	PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+	/* increment the src refcount */
+	PVRSRVKernelMemInfoIncRef(psSrcMemInfo);
+
+	/* Tell the buffer manager about the export */
+	BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
+
+	/* setup the resman map data */
+	psMapData->psMemInfo = psMemInfo;
+	psMapData->psSrcMemInfo = psSrcMemInfo;
+
+	/* Register Resource */
+	psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													RESMAN_TYPE_DEVICEMEM_MAPPING,
+													psMapData,
+													0,
+													&UnmapDeviceMemoryCallBack);
+#if defined (MEM_TRACK_INFO_DEBUG)
+	psBMHeap = (BM_HEAP*)hDstDevMemHeap;
+	hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+    	psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+    	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+    	for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+    	{
+        	if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+            	break;
+    	}
+
+    	if(i == PVRSRV_MAX_CLIENT_HEAPS)
+    	{
+        	PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: unable to find mapping heap"));
+        	eError = PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP;
+		OSStringCopy(psMemInfo->heapId, "Heap not found");
+    	}
+	else
+	    	OSStringCopy(psMemInfo->heapId, psDeviceMemoryHeap[i].pszName);
+#endif
+
+	*ppsDstMemInfo = psMemInfo;
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_MEM_TRACK_INFO), 
+						(IMG_VOID **)&psMemTrackInfo, IMG_NULL,
+						"Mem tracking info");
+	if (eError != PVRSRV_OK)
+		return eError;
+	psMemTrackInfo->sDevVAddr = psMemInfo->sDevVAddr;
+	psMemTrackInfo->uSize     = psMemInfo->uAllocSize;
+	psMemTrackInfo->ui32Pid = OSGetCurrentProcessIDKM();
+	psMemTrackInfo->ui32RefCount = psMemInfo->ui32RefCount;
+	psMemTrackInfo->eOp = PVRSRV_MEMTYPE_MAPPED;
+	psMemTrackInfo->ui32TimeStampUSecs = OSGetCurrentTimeInUSecsKM();
+
+	OSGetCurrentProcessNameKM(psMemTrackInfo->asTaskName, 128);
+	OSStringCopy(psMemTrackInfo->heapId, psMemInfo->heapId);
+
+	PVRSRVAddMemTrackInfo(psMemTrackInfo);
+#endif
+	return PVRSRV_OK;
+
+	/* error handling: */
+
+ErrorExit:
+
+	if(psSysPAddr)
+	{
+		/* Free the page address list */
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
+		/*not nulling shared pointer, holding structure could be not initialized*/
+	}
+
+	if(psMemInfo)
+	{
+		/* Free the page address list */
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+		/*not nulling shared pointer, holding structure could be not initialized*/
+	}
+
+	if(psMapData)
+	{
+		/* Free the resman map data */
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+	}
+
+	return eError;
+}
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+/*!
+******************************************************************************
+	@Function   PVRSRVUnmapDeviceClassMemoryKM
+
+	@Description  unmaps physical pages from devices address space at a specified
+				Device Virtual Address.
+				Note: this can only unmap memory mapped by
+				PVRSRVMapDeviceClassMemoryKM
+
+	@Input	    psMemInfo - mem info describing the device virtual address
+									to unmap RAM from
+	@Return     None
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+	if (!psMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+
+
+/*!
+******************************************************************************
+	@Function   UnmapDeviceClassMemoryCallBack
+
+	@Description Resman callback to unmap device class memory
+
+	@Input	    pvParam - opaque void ptr param
+	@Input	    ui32Param - opaque unsigned long param
+	@Return     PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID  pvParam,
+												   IMG_UINT32 ui32Param,
+												   IMG_BOOL   bDummy)
+{
+	PVRSRV_DC_MAPINFO *psDCMapInfo = pvParam;
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	psMemInfo = psDCMapInfo->psMemInfo;
+
+#if defined(SUPPORT_MEMORY_TILING)
+	if(psDCMapInfo->ui32TilingStride > 0)
+	{
+		PVRSRV_DEVICE_NODE *psDeviceNode = psDCMapInfo->psDeviceNode;
+
+		if (psDeviceNode->pfnFreeMemTilingRange(psDeviceNode,
+												psDCMapInfo->ui32RangeIndex) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceClassMemoryCallBack: FreeMemTilingRange failed"));
+		}
+	}
+#endif
+
+	(psDCMapInfo->psDeviceClassBuffer->ui32MemMapRefCount)--;
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), psDCMapInfo, IMG_NULL);
+
+	return FreeMemCallBackCommon(psMemInfo, ui32Param,
+								 PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+
+/*!
+******************************************************************************
+	@Function   PVRSRVMapDeviceClassMemoryKM
+
+	@Description  maps physical pages for DeviceClass buffers into a devices
+				address space at a specified and pre-allocated Device
+				Virtual Address
+
+	@Input	    psPerProc - Per-process data
+	@Input	    hDevMemContext - Device memory context
+	@Input	    hDeviceClassBuffer - Device Class Buffer (Surface) handle
+	@Input	    hDevMemContext - device memory context to which mapping
+										is made
+	@Output     ppsMemInfo - mem info describing the mapped memory
+	@Output     phOSMapInfo - OS specific mapping information
+	@Return     None
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+													   IMG_HANDLE				hDevMemContext,
+													   IMG_HANDLE				hDeviceClassBuffer,
+													   PVRSRV_KERNEL_MEM_INFO	**ppsMemInfo,
+													   IMG_HANDLE				*phOSMapInfo)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_DEVICE_NODE* psDeviceNode;
+	PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+	PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+	IMG_SYS_PHYADDR *psSysPAddr;
+	IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+	IMG_BOOL bPhysContig;
+	BM_CONTEXT *psBMContext;
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+	IMG_HANDLE hDevMemHeap = IMG_NULL;
+	IMG_UINT32 ui32ByteSize;
+	IMG_SIZE_T uOffset;
+	IMG_SIZE_T uPageSize = HOST_PAGESIZE();
+	BM_HANDLE		hBuffer;
+	PVRSRV_MEMBLK	*psMemBlock;
+	IMG_BOOL		bBMError;
+	IMG_UINT32 i;
+	PVRSRV_DC_MAPINFO *psDCMapInfo = IMG_NULL;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	PVRSRV_MEM_TRACK_INFO  *psMemTrackInfo;
+	IMG_CHAR *pszName = "Heap not found";
+#endif
+	if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* allocate resman storage structure */
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(PVRSRV_DC_MAPINFO),
+					(IMG_VOID **)&psDCMapInfo, IMG_NULL,
+					"PVRSRV_DC_MAPINFO") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for psDCMapInfo"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet(psDCMapInfo, 0, sizeof(PVRSRV_DC_MAPINFO));
+
+	psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
+
+	/*
+		call into external driver to get info so we can map a meminfo
+		Notes:
+		It's expected that third party displays will only support
+		physically contiguous display surfaces.  However, it's possible
+		a given display may have an MMU and therefore support non-contig'
+		display surfaces.
+
+		If surfaces are contiguous, ext driver should return:
+		 - a CPU virtual address, or IMG_NULL where the surface is not mapped to CPU
+		 - (optional) an OS Mapping handle for KM->UM surface mapping
+		 - the size in bytes
+		 - a single system physical address
+
+		If surfaces are non-contiguous, ext driver should return:
+		 - a CPU virtual address
+		 - (optional) an OS Mapping handle for KM->UM surface mapping
+		 - the size in bytes (must be multiple of 4kB)
+		 - a list of system physical addresses (at 4kB intervals)
+	*/
+	eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
+												   psDeviceClassBuffer->hExtBuffer,
+												   &psSysPAddr,
+												   &ui32ByteSize,
+												   &pvCPUVAddr,
+												   phOSMapInfo,
+												   &bPhysContig,
+												   &psDCMapInfo->ui32TilingStride);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+		goto ErrorExitPhase1;
+	}
+
+	/* Choose the heap to map to */
+	psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
+	psDeviceNode = psBMContext->psDeviceNode;
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+	for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+	{
+		if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+		{
+			if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+			{
+				if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+				{
+					hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+				#if defined (MEM_TRACK_INFO_DEBUG)
+					pszName = psDeviceMemoryHeap[i].pszName;
+				#endif
+				}
+				else
+				{
+					hDevMemHeap = IMG_NULL;
+				}
+			}
+			else
+			{
+				hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+			#if defined (MEM_TRACK_INFO_DEBUG)
+				pszName = psDeviceMemoryHeap[i].pszName;
+			#endif
+			}
+			break;
+		}
+	}
+
+	if(hDevMemHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap"));
+		eError = PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE;
+		goto ErrorExitPhase1;
+	}
+
+	/* Only need lower 12 bits of the cpu addr - don't care what size a void* is */
+	uOffset = ((IMG_UINTPTR_T)pvCPUVAddr) & (uPageSize - 1);
+	pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - uOffset);
+
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(PVRSRV_KERNEL_MEM_INFO),
+					(IMG_VOID **)&psMemInfo, IMG_NULL,
+					"Kernel Memory Info");
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+		goto ErrorExitPhase1;
+	}
+
+	OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+	/*
+		Force the memory to be read/write. This used to be done in the BM, but
+		ion imports don't want this behaviour
+	*/
+	psMemInfo->ui32Flags |= PVRSRV_MEM_READ | PVRSRV_MEM_WRITE;
+
+	psMemBlock = &(psMemInfo->sMemBlk);
+
+	bBMError = BM_Wrap(hDevMemHeap,
+					   ui32ByteSize,
+					   uOffset,
+					   bPhysContig,
+					   psSysPAddr,
+					   pvPageAlignedCPUVAddr,
+					   &psMemInfo->ui32Flags,
+					   &hBuffer);
+
+	if (!bBMError)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
+		/*not nulling pointer, out of scope*/
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto ErrorExitPhase2;
+	}
+
+	/* Fill in "Implementation dependant" section of mem info */
+	psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+	psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+	/* Convert from BM_HANDLE to external IMG_HANDLE */
+	psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+	/* patch up the CPU VAddr into the meminfo - use the address from the BM, not the one from the deviceclass
+	   api, to ensure user mode mapping is possible
+	 */
+	psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+	/* Fill in the public fields of the MEM_INFO structure */
+	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+	psMemInfo->uAllocSize = ui32ByteSize;
+	psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
+
+	PVR_ASSERT(psMemInfo->psKernelSyncInfo != IMG_NULL);
+	if (psMemInfo->psKernelSyncInfo)
+	{
+		PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+	}
+
+	/* Clear the Backup buffer pointer as we do not have one at this point.
+	   We only allocate this as we are going up/down
+	 */
+	psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+	/* setup DCMapInfo */
+	psDCMapInfo->psMemInfo = psMemInfo;
+	psDCMapInfo->psDeviceClassBuffer = psDeviceClassBuffer;
+
+#if defined(SUPPORT_MEMORY_TILING)
+	psDCMapInfo->psDeviceNode = psDeviceNode;
+
+	if(psDCMapInfo->ui32TilingStride > 0)
+	{
+		/* try to acquire a tiling range on this device */
+		eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode,
+														psMemInfo,
+														psDCMapInfo->ui32TilingStride,
+														&psDCMapInfo->ui32RangeIndex);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: AllocMemTilingRange failed"));
+
+			if (psMemInfo->psKernelSyncInfo)
+			{
+				PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+			}
+			FreeDeviceMem(psMemInfo);
+
+			/* FreeDeviceMem will free the meminfo so jump straight to the final exit */
+			goto ErrorExitPhase1;
+		}
+	}
+#endif
+
+	/* Register Resource */
+	psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+													psDCMapInfo,
+													0,
+													&UnmapDeviceClassMemoryCallBack);
+
+	(psDeviceClassBuffer->ui32MemMapRefCount)++;
+	PVRSRVKernelMemInfoIncRef(psMemInfo);
+
+	psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	OSStringCopy(psMemInfo->heapId, pszName);
+#endif
+
+	/* return the meminfo */
+	*ppsMemInfo = psMemInfo;
+#if defined (MEM_TRACK_INFO_DEBUG)
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_MEM_TRACK_INFO), 
+						(IMG_VOID **)&psMemTrackInfo, IMG_NULL,
+						"Mem tracking info");
+	if (eError != PVRSRV_OK)
+		return eError;
+	psMemTrackInfo->sDevVAddr = psMemInfo->sDevVAddr;
+	psMemTrackInfo->uSize     = psMemInfo->uAllocSize;
+	psMemTrackInfo->ui32Pid = OSGetCurrentProcessIDKM();
+	psMemTrackInfo->ui32RefCount = psMemInfo->ui32RefCount;
+	psMemTrackInfo->eOp = PVRSRV_MEMTYPE_DEVICECLASS;
+	psMemTrackInfo->ui32TimeStampUSecs = OSGetCurrentTimeInUSecsKM();
+
+	OSGetCurrentProcessNameKM(psMemTrackInfo->asTaskName, 128);
+
+	OSStringCopy(psMemTrackInfo->heapId, psMemInfo->heapId);
+	PVRSRVAddMemTrackInfo(psMemTrackInfo);
+#endif
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	/* If the 3PDD supplies a kernel virtual address, we can PDUMP it */
+	if(psMemInfo->pvLinAddrKM)
+	{
+		/* FIXME:
+		 *	Initialise the display surface here when it is mapped into Services.
+		 *	Otherwise there is a risk that pdump toolchain will assign previously
+		 *	used physical pages, leading to visual artefacts on the unrendered surface
+		 *	(e.g. during LLS rendering).
+		 *
+		 *	A better method is to pdump the allocation from the DC driver, so the
+		 *	BM_Wrap pdumps only the virtual memory which better represents the driver
+		 *	behaviour.	
+		 */
+		PDUMPCOMMENT("Dump display surface");
+		PDUMPMEM(IMG_NULL, psMemInfo, uOffset, psMemInfo->uAllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+	}
+#endif
+	return PVRSRV_OK;
+
+ErrorExitPhase2:
+	OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ErrorExitPhase1:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), psDCMapInfo, IMG_NULL);
+	return eError;
+}
+
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVChangeDeviceMemoryAttributesKM(IMG_HANDLE hKernelMemInfo, IMG_UINT32 ui32Attribs)
+{
+	PVRSRV_KERNEL_MEM_INFO		*psKMMemInfo;
+
+	if (hKernelMemInfo == IMG_NULL)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psKMMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hKernelMemInfo;
+
+	if (ui32Attribs & PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT)
+	{
+		psKMMemInfo->ui32Flags |= PVRSRV_MEM_CACHE_CONSISTENT;
+	}
+	else
+	{
+		psKMMemInfo->ui32Flags &= ~PVRSRV_MEM_CACHE_CONSISTENT;
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitDeviceMem(IMG_VOID)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(SUPPORT_ION)
+	/*
+		For Ion buffers we need to store which ones we know about so
+		we don't give the same buffer a different sync
+	*/
+	g_psIonSyncHash = HASH_Create(ION_SYNC_HASH_SIZE);
+	if (!g_psIonSyncHash)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto Error;
+	}
+#endif
+#if defined(SUPPORT_DMABUF)
+	g_psDmaBufSyncHash = HASH_Create(DMABUF_SYNC_HASH_SIZE);
+	if (!g_psDmaBufSyncHash)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto Error;
+	}
+#endif
+
+#if defined(SUPPORT_ION) || defined(SUPPORT_DMABUF)
+	return PVRSRV_OK;
+Error:
+#endif
+#if defined(SUPPORT_DMABUF)
+	if (g_psDmaBufSyncHash)
+	{
+		HASH_Delete(g_psDmaBufSyncHash);
+	}
+#endif
+#if defined(SUPPORT_ION)
+	if (g_psIonSyncHash)
+	{
+		HASH_Delete(g_psIonSyncHash);
+	}
+#endif
+	return eError;
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInitDeviceMem(IMG_VOID)
+{
+#if defined(SUPPORT_DMABUF)
+	HASH_Delete(g_psDmaBufSyncHash);
+#endif
+#if defined(SUPPORT_ION)
+	HASH_Delete(g_psIonSyncHash);
+#endif
+}
+
+#if defined(MEM_TRACK_INFO_DEBUG)
+/*!
+******************************************************************************
+
+ @Function 	PVRSRVFreeMemOps
+
+ @Description
+ Frees the list of tracked mem ops represented by g_psMemTrackInfoHead
+
+ @Input
+ @Output
+
+ @Return
+
+******************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVFreeMemOps(IMG_VOID)
+{
+	PVRSRV_MEM_TRACK_INFO *psFreePtr;
+	while(g_psMemTrackInfoHead)
+	{
+		psFreePtr = g_psMemTrackInfoHead;
+		g_psMemTrackInfoHead = g_psMemTrackInfoHead->next;
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+						sizeof(PVRSRV_MEM_TRACK_INFO),
+						psFreePtr, IMG_NULL);
+	}
+}
+#endif		
+
+static PVRSRV_ERROR PVRSRVDumpSync(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+	PVR_LOG(("\tSyncInfo %d:", psKernelSyncInfo->ui32UID));
+	PVR_LOG(("\t\tWrite ops (0x%08x): P/C = %d/%d (0x%08x/0x%08x)",
+				psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+				psKernelSyncInfo->psSyncData->ui32WriteOpsPending,
+				psKernelSyncInfo->psSyncData->ui32WriteOpsComplete,
+				psKernelSyncInfo->psSyncData->ui32WriteOpsPending,
+				psKernelSyncInfo->psSyncData->ui32WriteOpsComplete));
+	PVR_LOG(("\t\tRead ops (0x%08x): P/C = %d/%d (0x%08x/0x%08x)",
+				psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+				psKernelSyncInfo->psSyncData->ui32ReadOpsPending,
+				psKernelSyncInfo->psSyncData->ui32ReadOpsComplete,
+				psKernelSyncInfo->psSyncData->ui32ReadOpsPending,
+				psKernelSyncInfo->psSyncData->ui32ReadOpsComplete));
+	PVR_LOG(("\t\tRead ops 2 (0x%08x): P/C = %d/%d (0x%08x/0x%08x)",
+				psKernelSyncInfo->sReadOps2CompleteDevVAddr.uiAddr,
+				psKernelSyncInfo->psSyncData->ui32ReadOps2Pending,
+				psKernelSyncInfo->psSyncData->ui32ReadOps2Complete,
+				psKernelSyncInfo->psSyncData->ui32ReadOps2Pending,
+				psKernelSyncInfo->psSyncData->ui32ReadOps2Complete));
+
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+	{
+		IMG_UINT32 i;
+		PVR_LOG(("\t\t --- Per sync debug ---"));
+
+		PVR_LOG(("\t\tOperationMask = 0x%08x", psKernelSyncInfo->ui32OperationMask));
+
+
+		for (i=0;i<PER_SYNC_HISTORY;i++)
+		{
+			IMG_UINT32 ui32Index = (i + psKernelSyncInfo->ui32HistoryIndex) % PER_SYNC_HISTORY;
+			IMG_UINT32 ui32OpInfo = psKernelSyncInfo->aui32OpInfo[ui32Index];
+
+			if (ui32OpInfo & SYNC_OP_HAS_DATA)
+			{
+				IMG_UINT32 ui32OpClass = (ui32OpInfo & SYNC_OP_CLASS_MASK) >> SYNC_OP_CLASS_SHIFT;
+				IMG_UINT32 ui32OpType = (ui32OpInfo & SYNC_OP_TYPE_MASK) >> SYNC_OP_TYPE_SHIFT;
+				IMG_CHAR *pzClass;
+				IMG_CHAR *pzType;
+
+				PVR_LOG(("\t\tOperation last - %d\n", PER_SYNC_HISTORY - i));
+
+				switch(ui32OpClass)
+				{
+					case SYNC_OP_CLASS_MODOBJ:
+								pzClass = "MODOBJ";
+								break;
+					case SYNC_OP_CLASS_QUEUE:
+								pzClass = "QUEUE";
+								break;
+					case SYNC_OP_CLASS_KICKTA:
+								pzClass = "KICKTA";
+								break;
+					case SYNC_OP_CLASS_TQ_3D:
+								pzClass = "TQ_3D";
+								break;
+					case SYNC_OP_CLASS_TQ_2D:
+								pzClass = "TQ_2D";
+								break;
+					default:
+								pzClass = "Unknown";
+				}
+				switch(ui32OpType)
+				{
+					case SYNC_OP_TYPE_READOP:
+								pzType = "READOP";
+								break;
+					case SYNC_OP_TYPE_WRITEOP:
+								pzType = "WRITEOP";
+								break;
+					case SYNC_OP_TYPE_READOP2:
+								pzType = "READOP2";
+								break;
+					default:
+								pzType = "Unknown";
+				}
+				PVR_LOG(("\t\t\tui32OpType = 0x%08x", ui32OpInfo));
+				PVR_LOG(("\t\t\t\t%s, %s, %s, %s",
+							pzClass,
+							pzType,
+							(ui32OpInfo & SYNC_OP_TAKE) ?"TAKE":"No TAKE",
+							(ui32OpInfo & SYNC_OP_ROLLBACK) ?"ROLLBACK":"No ROLLBACK"));
+
+				PVR_LOG(("\t\t\ti32ReadOpSample = %d (0x%08x)",
+							psKernelSyncInfo->aui32ReadOpSample[ui32Index],
+							psKernelSyncInfo->aui32ReadOpSample[ui32Index]));
+				PVR_LOG(("\t\t\taui32WriteOpSample = %d (0x%08x)",
+							psKernelSyncInfo->aui32WriteOpSample[ui32Index],
+							psKernelSyncInfo->aui32WriteOpSample[ui32Index]));
+				PVR_LOG(("\t\t\taui32ReadOp2Sample = %d (0x%08x)",
+							psKernelSyncInfo->aui32ReadOp2Sample[ui32Index],
+							psKernelSyncInfo->aui32ReadOp2Sample[ui32Index]));
+			}
+		}
+	}
+#endif
+	return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVDumpActiveSync(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+	if ((psKernelSyncInfo->psSyncData->ui32WriteOpsComplete != psKernelSyncInfo->psSyncData->ui32WriteOpsPending) ||
+		(psKernelSyncInfo->psSyncData->ui32ReadOpsComplete != psKernelSyncInfo->psSyncData->ui32ReadOpsPending) ||
+		(psKernelSyncInfo->psSyncData->ui32ReadOps2Complete != psKernelSyncInfo->psSyncData->ui32ReadOps2Pending))
+	{
+		PVRSRVDumpSync(psKernelSyncInfo);
+	}
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVDumpSyncs(IMG_BOOL bActiveOnly)
+{
+	if (bActiveOnly)
+	{
+		PVR_LOG(("Active syncs"));
+		List_PVRSRV_KERNEL_SYNC_INFO_PVRSRV_ERROR_Any(g_psSyncInfoList, PVRSRVDumpActiveSync);
+	}
+	else
+	{
+		PVR_LOG(("All syncs"));
+		List_PVRSRV_KERNEL_SYNC_INFO_PVRSRV_ERROR_Any(g_psSyncInfoList, PVRSRVDumpSync);
+	}
+}
+/******************************************************************************
+ End of file (devicemem.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/handle.c b/drivers/gpu/pvr/services4/srvkm/common/handle.c
new file mode 100644
index 0000000..b1ac749
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/handle.c
@@ -0,0 +1,2548 @@
+/*************************************************************************/ /*!
+@Title          Resource Handle Manager
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provide resource handle management
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if defined(PVR_SECURE_HANDLES)
+/* See handle.h for a description of the handle API. */
+
+/*
+ * There is no locking here.  It is assumed the code is used in a single
+ * threaded environment.  In particular, it is assumed that the code will
+ * never be called from an interrupt handler.
+ *
+ * The implementation supports movable handle structures, allowing the address
+ * of a handle structure to change without having to fix up pointers in
+ * any of the handle structures.  For example, the linked list mechanism
+ * used to link subhandles together uses handle array indices rather than
+ * pointers to the structures themselves.
+ */
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "handle.h"
+
+#ifdef	DEBUG
+#define	HANDLE_BLOCK_SHIFT	2
+#else
+#define	HANDLE_BLOCK_SHIFT	8
+#endif
+
+#define	DIVIDE_BY_BLOCK_SIZE(i)		(((IMG_UINT32)(i)) >> HANDLE_BLOCK_SHIFT)
+#define	MULTIPLY_BY_BLOCK_SIZE(i)	(((IMG_UINT32)(i)) << HANDLE_BLOCK_SHIFT)
+
+#define HANDLE_BLOCK_SIZE       MULTIPLY_BY_BLOCK_SIZE(1)
+#define	HANDLE_SUB_BLOCK_MASK	(HANDLE_BLOCK_SIZE - 1)
+#define	HANDLE_BLOCK_MASK	(~(HANDLE_SUB_BLOCK_MASK))
+
+#define	HANDLE_HASH_TAB_INIT_SIZE	32
+
+#define	INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+/* Valid handles are never NULL, but handle array indices are based from 0 */
+#define	INDEX_TO_HANDLE(i) ((IMG_HANDLE)((IMG_UINTPTR_T)(i) + 1))
+#define	HANDLE_TO_INDEX(h) ((IMG_UINT32)(IMG_UINTPTR_T)(h) - 1)
+
+
+#define	INDEX_TO_BLOCK_INDEX(i)		DIVIDE_BY_BLOCK_SIZE(i)
+#define BLOCK_INDEX_TO_INDEX(i)		MULTIPLY_BY_BLOCK_SIZE(i)
+#define INDEX_TO_SUB_BLOCK_INDEX(i)	((i) & HANDLE_SUB_BLOCK_MASK)
+
+#define INDEX_TO_INDEX_STRUCT_PTR(psArray, i) (&((psArray)[INDEX_TO_BLOCK_INDEX(i)]))
+#define	BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i) INDEX_TO_INDEX_STRUCT_PTR((psBase)->psHandleArray, i)
+
+#define	INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->ui32FreeHandBlockCount)
+
+#define INDEX_TO_HANDLE_STRUCT_PTR(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->psHandle + INDEX_TO_SUB_BLOCK_INDEX(i))
+
+#define	HANDLE_TO_HANDLE_STRUCT_PTR(psBase, h) (INDEX_TO_HANDLE_STRUCT_PTR(psBase, HANDLE_TO_INDEX(h)))
+
+#define	HANDLE_PTR_TO_INDEX(psHandle) ((psHandle)->ui32Index)
+#define	HANDLE_PTR_TO_HANDLE(psHandle) INDEX_TO_HANDLE(HANDLE_PTR_TO_INDEX(psHandle))
+
+#define	ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(a) (HANDLE_BLOCK_MASK & (a))
+#define	ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(a) ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE((a) + HANDLE_BLOCK_SIZE - 1)
+
+#define	DEFAULT_MAX_HANDLE		0x7fffffffu
+#define	DEFAULT_MAX_INDEX_PLUS_ONE	ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(DEFAULT_MAX_HANDLE)
+
+#define	HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define HANDLE_ARRAY_SIZE(handleCount) DIVIDE_BY_BLOCK_SIZE(ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(handleCount))
+
+#define	SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
+#define	CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
+#define	TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
+
+#define	TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
+
+#define	SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
+#define	CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
+#define	TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
+
+#define	BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define	SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define	SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define	BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define	HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
+
+#ifdef	MIN
+#undef MIN
+#endif
+
+#define	MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+/*
+ * Linked list structure.  Used for both the list head and list items.
+ * Array indices, rather than pointers, are used to point to the next and
+ * previous items on the list.
+ */
+struct sHandleList
+{
+	IMG_UINT32 ui32Prev;
+	IMG_UINT32 ui32Next;
+	IMG_HANDLE hParent;
+};
+
+enum ePVRSRVInternalHandleFlag
+{
+	INTERNAL_HANDLE_FLAG_NONE = 0x00,
+	INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
+	INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
+};
+
+/* Handle structure */
+struct sHandle
+{
+	/* Handle type */
+	PVRSRV_HANDLE_TYPE eType;
+
+	/* Pointer to the data that the handle represents */
+	IMG_VOID *pvData;
+
+	/*
+	 * When handles are on the free list, the value of the "next index
+	 * plus one field" has the following meaning:
+	 * zero - next handle is the one that follows this one,
+	 * nonzero - the index of the next handle is the value minus one.
+	 * This scheme means handle space can be initialised to all zeros.
+	 *
+	 * When this field is used to link together handles on a list
+	 * other than the free list, zero indicates the end of the
+	 * list, with nonzero the same as above.
+	 */
+	IMG_UINT32 ui32NextIndexPlusOne;
+
+	/* Internal flags */
+	enum ePVRSRVInternalHandleFlag eInternalFlag;
+
+	/* Flags specified when the handle was allocated */
+	PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+	/* Index of this handle in the handle array */
+	IMG_UINT32 ui32Index;
+
+	/* List head for subhandles of this handle */
+	struct sHandleList sChildren;
+
+	/* List entry for sibling subhandles */
+	struct sHandleList sSiblings;
+};
+
+/* Handle array index structure.
+ * The handle array is an array of index structures, reallocated as the number of
+ * handles increases.
+ * NOTE: There is one index structure per block of handles.
+ */
+struct sHandleIndex
+{
+	/* Pointer to first handle structure in the block */
+	struct sHandle *psHandle;
+
+	/* Block allocation cookie returned from OSAllocMem for the block of handles */
+	IMG_HANDLE hBlockAlloc;
+
+	/* Number of free handles in block */
+	IMG_UINT32 ui32FreeHandBlockCount;
+};
+
+struct _PVRSRV_HANDLE_BASE_
+{
+	/*  Handle returned from OSAllocMem for handle base allocation */
+	IMG_HANDLE hBaseBlockAlloc;
+
+	/* Handle returned from OSAllocMem for handle array allocation */
+	IMG_HANDLE hArrayBlockAlloc;
+
+	/* Pointer to array of pointers to handle structures */
+	struct sHandleIndex *psHandleArray;
+
+	/*
+	 * Pointer to handle hash table.
+	 * The hash table is used to do reverse lookups, converting data
+	 * pointers to handles.
+	 */
+	HASH_TABLE *psHashTab;
+
+	/* Number of free handles */
+	IMG_UINT32 ui32FreeHandCount;
+
+	/*
+	 * If purging is not enabled, this is the array index of first free
+	 * handle.
+	 * If purging is enabled, this is the index to start searching for
+	 * a free handle from.  In this case it is usually zero, unless
+	 * the handle array size has been increased due to lack of
+	 * handles.
+	 */
+	IMG_UINT32 ui32FirstFreeIndex;
+
+	/* Maximum handle index, plus one */
+	IMG_UINT32 ui32MaxIndexPlusOne;
+
+	/* Total number of handles, free and allocated */
+	IMG_UINT32 ui32TotalHandCount;
+
+	/*
+	 * Index of the last free index, plus one. Not used if purging
+	 * is enabled.
+	 */
+	IMG_UINT32 ui32LastFreeIndexPlusOne;
+
+	/* Size of current handle batch, or zero if batching not enabled */
+	IMG_UINT32 ui32HandBatchSize;
+
+	/* Number of handles prior to start of current batch */
+	IMG_UINT32 ui32TotalHandCountPreBatch;
+
+	/* Index of first handle in batch, plus one */
+	IMG_UINT32 ui32FirstBatchIndexPlusOne;
+
+	/* Number of handle allocation failures in batch */
+	IMG_UINT32 ui32BatchHandAllocFailures;
+
+	/* Purging enabled.
+	 * If purging is enabled, the size of the table can be reduced
+	 * by removing free space at the end of the table.  To make
+	 * purging more likely to succeed, handles are allocated as
+	 * far to the front of the table as possible.  The first free
+	 * handle is found by a linear search from the start of the table,
+	 * and so no free handle list management is done.
+	 */
+	IMG_BOOL bPurgingEnabled;
+};
+
+/*
+ * The key for the handle hash table is an array of three elements, the
+ * pointer to the resource, the resource type, and the process ID.  The
+ * eHandKey enumeration gives the array indices of the elements making
+ * up the key.
+ */
+enum eHandKey {
+	HAND_KEY_DATA = 0,
+	HAND_KEY_TYPE,
+	HAND_KEY_PARENT,
+	HAND_KEY_LEN			/* Must be last item in list */
+};
+
+/*
+ * Kernel handle base structure.  For handles that are not allocated on
+ * behalf of a particular process
+ */
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+
+/* HAND_KEY is the type of the hash table key */
+typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+
+/*!
+******************************************************************************
+
+ @Function	HandleListInit
+
+ @Description	Initialise a linked list structure embedded in a handle
+		structure.
+
+ @Input		ui32Index - index of handle in the handle array
+		psList - pointer to linked list structure
+		hParent - parent handle, or IMG_NULL
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInit)
+#endif
+static INLINE
+IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
+{
+	psList->ui32Next = ui32Index;
+	psList->ui32Prev = ui32Index;
+	psList->hParent = hParent;
+}
+
+/*!
+******************************************************************************
+
+ @Function	InitParentList
+
+ @Description	Initialise the children list head in a handle structure.
+		The children are the subhandles of this handle.
+
+ @Input		psHandle - pointer to handle structure
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitParentList)
+#endif
+static INLINE
+IMG_VOID InitParentList(struct sHandle *psHandle)
+{
+	IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psHandle);
+
+	HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
+}
+
+/*!
+******************************************************************************
+
+ @Function	InitChildEntry
+
+ @Description	Initialise the child list entry in a handle structure.
+		The list entry is used to link together subhandles of
+		a given handle.
+
+ @Input		psHandle - pointer to handle structure
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+IMG_VOID InitChildEntry(struct sHandle *psHandle)
+{
+	HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
+}
+
+/*!
+******************************************************************************
+
+ @Function	HandleListIsEmpty
+
+ @Description	Determine whether a given linked list is empty.
+
+ @Input		ui32Index - index of the handle containing the list head
+		psList - pointer to the list head
+
+ @Return	IMG_TRUE if the list is empty, IMG_FALSE if it isn't.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIsEmpty)
+#endif
+static INLINE
+IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
+{
+	IMG_BOOL bIsEmpty;
+
+	bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
+
+#ifdef	DEBUG
+	{
+		IMG_BOOL bIsEmpty2;
+
+		bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
+		PVR_ASSERT(bIsEmpty == bIsEmpty2);
+	}
+#endif
+
+	return bIsEmpty;
+}
+
+#ifdef DEBUG
+/*!
+******************************************************************************
+
+ @Function	NoChildren
+
+ @Description	Determine whether a handle has any subhandles
+
+ @Input		psHandle - pointer to handle structure
+
+ @Return	IMG_TRUE if the handle has no subhandles, IMG_FALSE if it does.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoChildren)
+#endif
+static INLINE
+IMG_BOOL NoChildren(struct sHandle *psHandle)
+{
+	PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle));
+
+	return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
+}
+
+/*!
+******************************************************************************
+
+ @Function	NoParent
+
+ @Description	Determine whether a handle is a subhandle
+
+ @Input		psHandle - pointer to handle structure
+
+ @Return	IMG_TRUE if the handle is not a subhandle, IMG_FALSE if it is.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+IMG_BOOL NoParent(struct sHandle *psHandle)
+{
+	if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
+	{
+		PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
+
+		return IMG_TRUE;
+	}
+	else
+	{
+		PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
+	}
+	return IMG_FALSE;
+}
+#endif /*DEBUG*/
+/*!
+******************************************************************************
+
+ @Function	ParentHandle
+
+ @Description	Determine the parent of a handle
+
+ @Input		psHandle - pointer to handle structure
+
+ @Return	Parent handle, or IMG_NULL if the handle is not a subhandle.
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentHandle)
+#endif
+static INLINE
+IMG_HANDLE ParentHandle(struct sHandle *psHandle)
+{
+	return psHandle->sSiblings.hParent;
+}
+
+/*
+ * The LIST_PTR_FROM_INDEX_AND_OFFSET macro is used to generate either a
+ * pointer to the subhandle list head, or a pointer to the linked list
+ * structure of an item on a subhandle list.
+ * The list head is itself on the list, but is at a different offset
+ * in the handle structure to the linked list structure for items on
+ * the list.  The two linked list structures are differentiated by
+ * the third parameter, containing the parent index.  The parent field
+ * in the list head structure references the handle structure that contains
+ * it.  For items on the list, the parent field in the linked list structure
+ * references the parent handle, which will be different from the handle
+ * containing the linked list structure.
+ */
+#define	LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
+		((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+
+/*!
+******************************************************************************
+
+ @Function	HandleListInsertBefore
+
+ @Description	Insert a handle before a handle currently on the list.
+
+ @Input		ui32InsIndex - index of handle to be inserted after
+		psIns - pointer to handle structure to be inserted after
+		uiParentOffset - offset to list head struct in handle structure
+		ui32EntryIndex - index of handle to be inserted
+		psEntry - pointer to handle structure of item to be inserted
+		uiEntryOffset - offset of list item struct in handle structure
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInsertBefore)
+#endif
+static INLINE
+IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
+{
+	/* PRQA S 3305 7 */ /*override stricter alignment warning */
+	struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
+
+	PVR_ASSERT(psEntry->hParent == IMG_NULL);
+	PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+	PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex));
+
+	psEntry->ui32Prev = psIns->ui32Prev;
+	psIns->ui32Prev = ui32EntryIndex;
+	psEntry->ui32Next = ui32InsIndex;
+	psPrevIns->ui32Next = ui32EntryIndex;
+
+	psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
+}
+
+/*!
+******************************************************************************
+
+ @Function	AdoptChild
+
+ @Description	Assign a subhandle to a handle
+
+ @Input		psParent - pointer to handle structure of parent handle
+		psChild - pointer to handle structure of child subhandle
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(AdoptChild)
+#endif
+static INLINE
+IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
+{
+	IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
+
+	PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent));
+
+	HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
+
+}
+
+/*!
+******************************************************************************
+
+ @Function	HandleListRemove
+
+ @Description	Remove a handle from a list
+
+ @Input		ui32EntryIndex - index of handle to be removed
+		psEntry - pointer to handle structure of item to be removed
+		uiEntryOffset - offset of list item struct in handle structure
+		uiParentOffset - offset to list head struct in handle structure
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListRemove)
+#endif
+static INLINE
+IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
+{
+	if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
+	{
+		/* PRQA S 3305 3 */ /*override stricter alignment warning */
+		struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+		struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+
+		/*
+		 * The list head is on the list, and we don't want to
+		 * remove it.
+		 */
+		PVR_ASSERT(psEntry->hParent != IMG_NULL);
+
+		psPrev->ui32Next = psEntry->ui32Next;
+		psNext->ui32Prev = psEntry->ui32Prev;
+
+		HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	UnlinkFromParent
+
+ @Description	Remove a subhandle from its parents list
+
+ @Input		psHandle - pointer to handle structure of child subhandle
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(UnlinkFromParent)
+#endif
+static INLINE
+IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
+}
+
+/*!
+******************************************************************************
+
+ @Function	HandleListIterate
+
+ @Description	Iterate over the items in a list
+
+ @Input		psHead - pointer to list head
+		uiParentOffset - offset to list head struct in handle structure
+		uiEntryOffset - offset of list item struct in handle structure
+		pfnIterFunc - function to be called for each handle in the list
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIterate)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead, IMG_SIZE_T uiParentOffset, IMG_SIZE_T uiEntryOffset, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+	IMG_UINT32 ui32Index;
+	IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
+
+	PVR_ASSERT(psHead->hParent != IMG_NULL);
+
+	/*
+ 	 * Follow the next chain from the list head until we reach
+ 	 * the list head again, which signifies the end of the list.
+ 	 */
+	for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
+	{
+		struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+		/* PRQA S 3305 2 */ /*override stricter alignment warning */
+		struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
+		PVRSRV_ERROR eError;
+
+		PVR_ASSERT(psEntry->hParent == psHead->hParent);
+		/*
+		 * Get the next index now, in case the list item is
+		 * modified by the iteration function.
+		 */
+		ui32Index = psEntry->ui32Next;
+
+		eError = (*pfnIterFunc)(psBase, psHandle);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	IterateOverChildren
+
+ @Description	Iterate over the subhandles of a parent handle
+
+ @Input		psParent - pointer to parent handle structure
+		pfnIterFunc - function to be called for each subhandle
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(IterateOverChildren)
+#endif
+static INLINE
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+	 return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
+}
+
+/*!
+******************************************************************************
+
+ @Function	GetHandleStructure
+
+ @Description	Get the handle structure for a given handle
+
+ @Input		psBase - pointer to handle base structure
+		ppsHandle - location to return pointer to handle structure
+		hHandle - handle from client
+		eType - handle type or PVRSRV_HANDLE_TYPE_NONE if the
+			handle type is not to be checked.
+
+ @Output	ppsHandle - points to a pointer to the handle structure
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleStructure)
+#endif
+static INLINE
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
+	struct sHandle *psHandle;
+
+	/* Check handle index is in range */
+	if (!INDEX_IS_VALID(psBase, ui32Index))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
+		return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+	}
+
+	psHandle =  INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+	if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
+		return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
+	}
+
+	/*
+	 * Unless PVRSRV_HANDLE_TYPE_NONE was passed in to this function,
+	 * check handle is of the correct type.
+	 */
+	if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
+		return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
+	}
+
+	/* Return the handle structure */
+	*ppsHandle = psHandle;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	ParentIfPrivate
+
+ @Description	Return the parent handle if the handle was allocated
+		with PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE, else return
+		IMG_NULL
+
+ @Input		psHandle - pointer to handle
+
+ @Return	Parent handle, or IMG_NULL
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentIfPrivate)
+#endif
+static INLINE
+IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
+{
+	return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+			ParentHandle(psHandle) : IMG_NULL;
+}
+
+/*!
+******************************************************************************
+
+ @Function	InitKey
+
+ @Description	Initialise a hash table key for the current process
+
+ @Input		psBase - pointer to handle base structure
+		aKey - pointer to key
+		pvData - pointer to the resource the handle represents
+		eType - type of resource
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitKey)
+#endif
+static INLINE
+IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
+	aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
+	aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
+}
+
+/*!
+******************************************************************************
+
+ @Function	ReallocHandleArray
+
+ @Description	Reallocate the handle array
+
+ @Input		psBase - handle base.
+		phBlockAlloc - pointer to block allocation handle.
+		ui32NewCount - new handle count
+		ui32OldCount - old handle count
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+static
+PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
+{
+	struct sHandleIndex *psOldArray = psBase->psHandleArray;
+	IMG_HANDLE hOldArrayBlockAlloc = psBase->hArrayBlockAlloc;
+	IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
+	struct sHandleIndex *psNewArray = IMG_NULL;
+	IMG_HANDLE hNewArrayBlockAlloc = IMG_NULL;
+	PVRSRV_ERROR eError;
+	PVRSRV_ERROR eReturn = PVRSRV_OK;
+	IMG_UINT32 ui32Index;
+
+	if (ui32NewCount == ui32OldCount)
+	{
+		return PVRSRV_OK;
+	}
+
+	if (ui32NewCount != 0 && !psBase->bPurgingEnabled &&
+		 ui32NewCount < ui32OldCount)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
+		((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
+	{
+		PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
+		PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);
+
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (ui32NewCount != 0)
+	{
+		/* Allocate new handle array */
+		eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+			HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+			(IMG_VOID **)&psNewArray,
+			&hNewArrayBlockAlloc,
+			"Memory Area");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate new handle array (%d)", eError));
+			eReturn = eError;
+			goto error;
+		}
+
+		if (ui32OldCount != 0)
+		{
+			OSMemCopy(psNewArray, psOldArray, HANDLE_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(struct sHandleIndex));
+		}
+	}
+
+	/*
+	 * If the new handle array is smaller than the old one, free
+	 * unused handle structures
+	 */
+	for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
+	{
+		struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
+
+		eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+				psIndex->psHandle,
+				psIndex->hBlockAlloc);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+		}
+	}
+
+	/*
+	 * If the new handle array is bigger than the old one, allocate
+	 * new handle structures
+	 */
+	for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+	{
+		/* PRQA S 0505 1 */ /* psNewArray is never NULL, see assert earlier */
+		struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+
+		eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+				(IMG_VOID **)&psIndex->psHandle,
+				&psIndex->hBlockAlloc,
+				"Memory Area");
+		if (eError != PVRSRV_OK)
+		{
+			psIndex->psHandle = IMG_NULL;
+			PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate handle structures (%d)", eError));
+			eReturn = eError;
+		}
+		else
+		{
+			IMG_UINT32 ui32SubIndex;
+
+			psIndex->ui32FreeHandBlockCount = HANDLE_BLOCK_SIZE;
+
+			for(ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
+			{
+				struct sHandle *psHandle = psIndex->psHandle + ui32SubIndex;
+
+
+				psHandle->ui32Index = ui32SubIndex + ui32Index;
+				psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+				psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+				psHandle->ui32NextIndexPlusOne  = 0;
+			}
+		}
+	}
+	if (eReturn != PVRSRV_OK)
+	{
+		goto error;
+	}
+
+#ifdef	DEBUG_MAX_HANDLE_COUNT
+	/* Force handle failure to test error exit code */
+	if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
+		eReturn = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto error;
+	}
+#endif
+
+	if (psOldArray != IMG_NULL)
+	{
+		/* Free old handle array */
+		eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
+			psOldArray,
+			hOldArrayBlockAlloc);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free old handle array (%d)", eError));
+		}
+	}
+
+	psBase->psHandleArray = psNewArray;
+	psBase->hArrayBlockAlloc = hNewArrayBlockAlloc;
+	psBase->ui32TotalHandCount = ui32NewCount;
+
+	if (ui32NewCount > ui32OldCount)
+	{
+		/* Check for wraparound */
+		PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount);
+
+		/* PRQA S 3382 1 */ /* ui32NewCount always > ui32OldCount */
+		psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
+
+		/*
+		 * If purging is enabled, there is no free handle list
+		 * management, but as an optimization, when allocating
+		 * new handles, we use ui32FirstFreeIndex to point to
+		 * the first handle in a newly allocated block.
+		 */
+		if (psBase->ui32FirstFreeIndex == 0)
+		{
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+			psBase->ui32FirstFreeIndex = ui32OldCount;
+		}
+		else
+		{
+			if (!psBase->bPurgingEnabled)
+			{
+				PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+				PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+
+				INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
+			}
+		}
+
+		if (!psBase->bPurgingEnabled)
+		{
+			psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
+		}
+	}
+	else
+	{
+		PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled);
+		PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount);
+		PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount);
+
+		/* PRQA S 3382 1 */ /* ui32OldCount always >= ui32NewCount */
+		psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
+
+		if (ui32NewCount == 0)
+		{
+			psBase->ui32FirstFreeIndex = 0;
+			psBase->ui32LastFreeIndexPlusOne = 0;
+		}
+	}
+
+	PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);
+
+	return PVRSRV_OK;
+
+error:
+	PVR_ASSERT(eReturn != PVRSRV_OK);
+
+	if (psNewArray != IMG_NULL)
+	{
+		/* Free any new handle structures that were allocated */
+		for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+		{
+			struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+			if (psIndex->psHandle != IMG_NULL)
+			{
+				eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+						psIndex->psHandle,
+						psIndex->hBlockAlloc);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+				}
+			}
+		}
+
+		/* Free new handle array */
+		eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+			psNewArray,
+			hNewArrayBlockAlloc);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free new handle array (%d)", eError));
+		}
+	}
+
+	return eReturn;
+}
+
+/*!
+******************************************************************************
+
+ @Function	FreeHandleArray
+
+ @Description	Frees the handle array.
+		The memory containing the array of handle structure
+		pointers is deallocated.
+
+ @Input		psBase - pointer to handle base structure
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
+{
+	return ReallocHandleArray(psBase, 0);
+}
+
+/*!
+******************************************************************************
+
+ @Function	FreeHandle
+
+ @Description	Free a handle structure.
+
+ @Input		psBase - pointer to handle base structure
+		psHandle - pointer to handle structure
+
+ @Return	PVRSRV_OK or PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+	HAND_KEY aKey;
+	IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
+	PVRSRV_ERROR eError;
+
+	/*
+	 * If a handle allocated in batch mode is freed whilst still
+	 * in batch mode, the type is set to PVRSRV_HANDLE_TYPE_NONE further
+	 * down, to indicate the handle will not be used, but not actually
+	 * freed.  The Free is completed when this function is called a
+	 * second time as part of the batch commit or release.
+	 */
+
+	InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
+
+	if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+	{
+		IMG_HANDLE hHandle;
+		hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
+
+
+		PVR_ASSERT(hHandle != IMG_NULL);
+		PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index));
+		PVR_UNREFERENCED_PARAMETER(hHandle);
+	}
+
+	/* Unlink handle from parent */
+	UnlinkFromParent(psBase, psHandle);
+
+	/* Free children */
+	eError = IterateOverChildren(psBase, psHandle, FreeHandle);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
+		return eError;
+	}
+
+	/*
+	 * Clear the type here, so that a handle can no longer be looked
+	 * up if it is only partially freed.
+	 */
+	psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+
+	if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+	{
+		/* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
+        SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
+		/*
+		 * If the handle was allocated in batch mode, delay the free
+		 * until the batch commit or release.
+		 */
+		return PVRSRV_OK;
+	}
+
+	/* No free list management if purging is enabled */
+	if (!psBase->bPurgingEnabled)
+	{
+		if (psBase->ui32FreeHandCount == 0)
+		{
+			PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+			psBase->ui32FirstFreeIndex =  ui32Index;
+		}
+		else
+		{
+			/*
+			 * Put the handle pointer on the end of the free
+			 * handle pointer linked list.
+			 */
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+			PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+			INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne =  ui32Index + 1;
+		}
+
+		PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
+
+		/* Update the end of the free handle linked list */
+		psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+	}
+
+	psBase->ui32FreeHandCount++;
+	INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
+
+	PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE);
+
+#ifdef DEBUG
+	{
+		IMG_UINT32 ui32BlockedIndex;
+		IMG_UINT32 ui32FreeHandCount = 0;
+
+		for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+		{
+			ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
+		}
+
+		PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount);
+	}
+#endif
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	FreeAllHandles
+
+ @Description	Free all handles for a given handle base
+
+ @Input		psBase - pointer to handle base structure
+
+ @Return	PVRSRV_OK or PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+	IMG_UINT32 i;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+	{
+		return eError;
+	}
+
+	for (i = 0; i < psBase->ui32TotalHandCount; i++)
+	{
+		struct sHandle *psHandle;
+
+		psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, i);
+
+		if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
+		{
+			eError = FreeHandle(psBase, psHandle);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
+				break;
+			}
+
+			/* Break out of loop if all the handles free */
+			if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+			{
+				break;
+			}
+		}
+	}
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	FreeHandleBase
+
+ @Description	Free a handle base.
+
+ @Input		psHandleBase - pointer to handle base
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVRSRV_ERROR eError;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
+		PVRSRVReleaseHandleBatch(psBase);
+	}
+
+	/* Free the handle array */
+	eError = FreeAllHandles(psBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
+		return eError;
+	}
+
+	/* Free the handle array */
+	eError = FreeHandleArray(psBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
+		return eError;
+	}
+
+	if (psBase->psHashTab != IMG_NULL)
+	{
+		/* Free the hash table */
+		HASH_Delete(psBase->psHashTab);
+	}
+
+	eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+		sizeof(*psBase),
+		psBase,
+		psBase->hBaseBlockAlloc);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	FindHandle
+
+ @Description	Find handle corresponding to a resource pointer
+
+ @Input		psBase - pointer to handle base structure
+		pvData - pointer to resource to be associated with the handle
+		eType - the type of resource
+
+ @Return	the handle, or IMG_NULL if not found
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(FindHandle)
+#endif
+static INLINE
+IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+	HAND_KEY aKey;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	InitKey(aKey, psBase, pvData, eType, hParent);
+
+	return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+/*!
+******************************************************************************
+
+ @Function	IncreaseHandleArraySize
+
+ @Description	Allocate some more free handles
+
+ @Input		psBase - pointer to handle base structure
+		ui32Delta - number of new handles required
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
+{
+	PVRSRV_ERROR eError;
+	IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
+	IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+
+	PVR_ASSERT(ui32Delta != 0);
+
+	/*
+	 * Check new count against max handle index, and check for wrap around.
+	 */
+	if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
+	{
+		ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
+
+		ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+		if (ui32DeltaAdjusted < ui32Delta)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+	}
+
+	PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
+
+	/* Realloc handle pointer array */
+	eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	EnsureFreeHandles
+
+ @Description	Ensure there are enough free handles
+
+ @Input		psBase - pointer to handle base structure
+		ui32Free - number of free handles required
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
+{
+	PVRSRV_ERROR eError;
+
+	if (ui32Free > psBase->ui32FreeHandCount)
+	{
+		IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
+		eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
+
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	AllocHandle
+
+ @Description	Allocate a new handle
+
+ @Input		phHandle - location for new handle
+		pvData - pointer to resource to be associated with the handle
+		eType - the type of resource
+		hParent - parent handle or IMG_NULL
+
+ @Output	phHandle - points to new handle
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+	IMG_UINT32 ui32NewIndex = DEFAULT_MAX_INDEX_PLUS_ONE;
+	struct sHandle *psNewHandle = IMG_NULL;
+	IMG_HANDLE hHandle;
+	HAND_KEY aKey;
+	PVRSRV_ERROR eError;
+
+	/* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+	PVR_ASSERT(psBase != IMG_NULL);
+	PVR_ASSERT(psBase->psHashTab != IMG_NULL);
+
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+		/* Handle must not already exist */
+		PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
+	}
+
+	if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
+	{
+		 PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize)); 
+	}
+
+	/* Ensure there is a free handle */
+	eError = EnsureFreeHandles(psBase, 1);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
+		return eError;
+	}
+	PVR_ASSERT(psBase->ui32FreeHandCount != 0);
+
+	if (!psBase->bPurgingEnabled)
+	{
+		/* Array index of first free handle */
+		ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+		/* Get handle array entry */
+		psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+	}
+	else
+	{
+		IMG_UINT32 ui32BlockedIndex;
+
+		/*
+		 * If purging is enabled, we always try to allocate handles
+		 * at the front of the array, to increase the chances that
+		 * the size of the handle array can be reduced by a purge.
+		 * No linked list of free handles is kept; we search for
+		 * free handles as required.
+		 */
+
+		/*
+		 * ui32FirstFreeIndex should only be set when a new batch of
+		 * handle structures is allocated, and should always be a
+		 * multiple of the block size.
+		 */
+		PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);
+
+		for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+		{
+			struct sHandleIndex *psIndex = BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, ui32BlockedIndex);
+
+			if (psIndex->ui32FreeHandBlockCount == 0)
+			{
+				continue;
+			}
+
+			for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
+			{
+				psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+				if (HANDLE_STRUCT_IS_FREE(psNewHandle))
+				{
+					break;
+				}
+			}
+		}
+		psBase->ui32FirstFreeIndex = 0;
+		PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
+	}
+	PVR_ASSERT(psNewHandle != IMG_NULL);
+
+	/* Handle to be returned to client */
+	hHandle = INDEX_TO_HANDLE(ui32NewIndex);
+
+	/*
+	 * If a data pointer can be associated with multiple handles, we
+	 * don't put the handle in the hash table, as the data pointer
+	 * may not map to a unique handle
+	 */
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+		/* Initialise hash key */
+		InitKey(aKey, psBase, pvData, eType, hParent);
+
+		/* Put the new handle in the hash table */
+		if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
+
+			return PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
+		}
+	}
+
+	psBase->ui32FreeHandCount--;
+
+	PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
+	PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0);
+
+	INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
+
+	/* No free list management if purging is enabled */
+	if (!psBase->bPurgingEnabled)
+	{
+		/* Check whether the last free handle has been allocated */
+		if (psBase->ui32FreeHandCount == 0)
+		{
+			PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+			PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
+
+			psBase->ui32LastFreeIndexPlusOne = 0;
+			psBase->ui32FirstFreeIndex = 0;
+		}
+		else
+		{
+			/*
+			 * Update the first free handle index.
+			 * If the "next free index plus one" field in the new
+			 * handle structure is zero, the next free index is
+			 * the index of the new handle plus one.  This
+			 * convention has been adopted to simplify the
+			 * initialisation of freshly allocated handle
+			 * space.
+			 */
+			psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
+				ui32NewIndex + 1 :
+				psNewHandle->ui32NextIndexPlusOne - 1;
+		}
+	}
+
+	/* Initialise the newly allocated handle */
+	PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex);
+
+	/* PRQA S 0505 1 */ /* psNewHandle is never NULL, see assert earlier */
+	psNewHandle->eType = eType;
+	psNewHandle->pvData = pvData;
+	psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+	psNewHandle->eFlag = eFlag;
+
+	InitParentList(psNewHandle);
+#if defined(DEBUG)
+	PVR_ASSERT(NoChildren(psNewHandle));
+#endif
+
+	InitChildEntry(psNewHandle);
+#if defined(DEBUG)
+	PVR_ASSERT(NoParent(psNewHandle));
+#endif
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		/* Add handle to batch list */
+		psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+
+		psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
+
+		/* PRQA S 1474 1 */ /* ignore warnings about enum types being modified */
+		SET_BATCHED_HANDLE(psNewHandle);
+	}
+	else
+	{
+		psNewHandle->ui32NextIndexPlusOne = 0;
+	}
+
+	/* Return the new handle to the client */
+	*phHandle = hHandle;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAllocHandle
+
+ @Description	Allocate a handle
+
+ @Input		phHandle - location for new handle
+		pvData - pointer to resource to be associated with the handle
+		eType - the type of resource
+
+ @Output	phHandle - points to new handle
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+	IMG_HANDLE hHandle;
+	PVRSRV_ERROR eError;
+
+	*phHandle = IMG_NULL;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		/*
+		 * Increment the counter in case of failure.  It will be
+		 * decremented on success.
+		 */
+		psBase->ui32BatchHandAllocFailures++;
+	}
+
+	/* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+		/* See if there is already a handle for this data pointer */
+		hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+		if (hHandle != IMG_NULL)
+		{
+			struct sHandle *psHandle;
+
+			eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
+				return eError;
+			}
+
+			/*
+			 * If the client is willing to share a handle, and the
+			 * existing handle is marked as shareable, return the
+			 * existing handle.
+			 */
+			if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
+			{
+				*phHandle = hHandle;
+				eError = PVRSRV_OK;
+				goto exit_ok;
+			}
+			
+			return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+		}
+	}
+
+	eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
+	
+exit_ok:
+	if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
+	{
+		psBase->ui32BatchHandAllocFailures--;
+	}
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAllocSubHandle
+
+ @Description	Allocate a subhandle
+
+ @Input		phHandle - location for new subhandle
+		pvData - pointer to resource to be associated with the subhandle
+		eType - the type of resource
+		hParent - parent handle
+
+ @Output	phHandle - points to new subhandle
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+	struct sHandle *psPHand;
+	struct sHandle *psCHand;
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hParentKey;
+	IMG_HANDLE hHandle;
+
+	*phHandle = IMG_NULL;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		/*
+		 * Increment the counter in case of failure.  It will be
+		 * decremented on success.
+		 */
+		psBase->ui32BatchHandAllocFailures++;
+	}
+
+	/* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+			hParent : IMG_NULL;
+
+	/* Lookup the parent handle */
+	eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+	{
+		/* See if there is already a handle for this data pointer */
+		hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+		if (hHandle != IMG_NULL)
+		{
+			struct sHandle *psCHandle;
+			PVRSRV_ERROR eErr;
+
+			eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
+			if (eErr != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+				return eErr;
+			}
+
+			PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent);
+
+			/*
+			 * If the client is willing to share a handle, the
+			 * existing handle is marked as shareable, and the
+			 * existing handle has the same parent, return the
+			 * existing handle.
+			 */
+			if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
+			{
+				*phHandle = hHandle;
+				goto exit_ok;
+			}
+			return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+		}
+	}
+
+	eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	/*
+	 * Get the parent handle structure again, in case the handle
+	 * structure has moved (depending on the implementation
+	 * of AllocHandle).
+	 */
+	psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
+
+	psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
+
+	AdoptChild(psBase, psPHand, psCHand);
+
+	*phHandle = hHandle;
+
+exit_ok:
+	if (HANDLES_BATCHED(psBase))
+	{
+		psBase->ui32BatchHandAllocFailures--;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVFindHandle
+
+ @Description	Find handle corresponding to a resource pointer
+
+ @Input		phHandle - location for returned handle
+		pvData - pointer to resource to be associated with the handle
+		eType - the type of resource
+
+ @Output	phHandle - points to handle
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+	IMG_HANDLE hHandle;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	/* See if there is a handle for this data pointer */
+	hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
+	if (hHandle == IMG_NULL)
+	{
+		return PVRSRV_ERROR_HANDLE_NOT_FOUND;
+	}
+
+	*phHandle = hHandle;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVLookupHandleAnyType
+
+ @Description	Lookup the data pointer and type corresponding to a handle
+
+ @Input		ppvData - location to return data pointer
+		peType - location to return handle type
+		hHandle - handle from client
+
+ @Output	ppvData - points to the data pointer
+		peType - points to handle type
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
+		OSDumpStack();
+		return eError;
+	}
+
+	*ppvData = psHandle->pvData;
+	*peType = psHandle->eType;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVLookupHandle
+
+ @Description	Lookup the data pointer corresponding to a handle
+
+ @Input		ppvData - location to return data pointer
+		hHandle - handle from client
+		eType - handle type
+
+ @Output	ppvData - points to the data pointer
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
+		OSDumpStack();
+		return eError;
+	}
+
+	*ppvData = psHandle->pvData;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVLookupSubHandle
+
+ @Description	Lookup the data pointer corresponding to a subhandle
+
+ @Input		ppvData - location to return data pointer
+		hHandle - handle from client
+		eType - handle type
+		hAncestor - ancestor handle
+
+ @Output	ppvData - points to the data pointer
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+	struct sHandle *psPHand;
+	struct sHandle *psCHand;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
+		OSDumpStack();
+		return eError;
+	}
+
+	/* Look for hAncestor among the handle's ancestors */
+	for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
+	{
+		eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+			return PVRSRV_ERROR_INVALID_SUBHANDLE;
+		}
+	}
+
+	*ppvData = psCHand->pvData;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetParentHandle
+
+ @Description	Lookup the parent of a handle
+
+ @Input		phParent - location for returning parent handle
+		hHandle - handle for which the parent handle is required
+		eType - handle type
+		hParent - parent handle
+
+ @Output	*phParent - parent handle, or IMG_NULL if there is no parent
+
+ @Return	Error code or PVRSRV_OK.  Note that not having a parent is
+		not regarded as an error.
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
+		OSDumpStack();
+		return eError;
+	}
+
+	*phParent = ParentHandle(psHandle);
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVLookupAndReleaseHandle
+
+ @Description	Lookup the data pointer corresponding to a handle
+
+ @Input		ppvData - location to return data pointer
+		hHandle - handle from client
+		eType - handle type
+		eFlag - lookup flags
+
+ @Output	ppvData - points to the data pointer
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
+		OSDumpStack();
+		return eError;
+	}
+
+	*ppvData = psHandle->pvData;
+
+	eError = FreeHandle(psBase, psHandle);
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVReleaseHandle
+
+ @Description	Release a handle that is no longer needed
+
+ @Input 	hHandle - handle from client
+		eType - handle type
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	struct sHandle *psHandle;
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+	eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
+		OSDumpStack();
+		return eError;
+	}
+
+	eError = FreeHandle(psBase, psHandle);
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVNewHandleBatch
+
+ @Description	Start a new handle batch
+
+ @Input 	psBase		- handle base
+ @Input 	ui32BatchSize	- handle batch size
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+	PVRSRV_ERROR eError;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
+		return  PVRSRV_ERROR_HANDLE_BATCH_IN_USE;
+	}
+
+	if (ui32BatchSize == 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
+		return  PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = EnsureFreeHandles(psBase, ui32BatchSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
+		return eError;
+	}
+
+	psBase->ui32HandBatchSize = ui32BatchSize;
+
+	/* Record current number of handles */
+	psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
+
+	PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
+
+	PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
+
+	PVR_ASSERT(HANDLES_BATCHED(psBase));
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVHandleBatchCommitOrRelease
+
+ @Description	Release a handle batch
+
+ @Input 	psBase	- handle base
+		bCommit	- commit handles
+
+ @Return	none
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
+{
+
+	IMG_UINT32 ui32IndexPlusOne;
+	IMG_BOOL bCommitBatch = bCommit;
+
+	if (!HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+
+	}
+
+	if (psBase->ui32BatchHandAllocFailures != 0)
+	{
+		if (bCommit)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
+		}
+		bCommitBatch = IMG_FALSE;
+	}
+	/*
+	 * The whole point of batched handles is to avoid handle allocation
+	 * failures.
+	 */
+	PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
+
+	ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+	while(ui32IndexPlusOne != 0)
+	{
+		struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
+		IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
+		PVR_ASSERT(BATCHED_HANDLE(psHandle));
+
+		psHandle->ui32NextIndexPlusOne = 0;
+
+		if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+		{
+			PVRSRV_ERROR eError;
+
+			/*
+			 * We need a complete free here.  If the handle
+			 * is not partially free, set the handle as
+			 * unbatched to avoid a partial free.
+			 */
+			if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+			{
+				/* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
+				SET_UNBATCHED_HANDLE(psHandle); /* PRQA S 4130 */ /* mis-use of enums FIXME*/
+			}
+
+			eError = FreeHandle(psBase, psHandle);
+			if (eError != PVRSRV_OK)
+			{
+				 PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
+			}
+			PVR_ASSERT(eError == PVRSRV_OK);
+		}
+		else
+		{
+			/* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
+			SET_UNBATCHED_HANDLE(psHandle);
+		}
+
+		ui32IndexPlusOne = ui32NextIndexPlusOne;
+	}
+
+#ifdef DEBUG
+	if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
+	{
+		IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
+
+		PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
+
+		PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small.  Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize,  psBase->ui32HandBatchSize + ui32Delta));
+
+	}
+#endif
+
+	psBase->ui32HandBatchSize = 0;
+	psBase->ui32FirstBatchIndexPlusOne = 0;
+	psBase->ui32TotalHandCountPreBatch = 0;
+	psBase->ui32BatchHandAllocFailures = 0;
+
+	if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
+	{
+		PVR_ASSERT(!bCommitBatch);
+
+		return PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVCommitHandleBatch
+
+ @Description	Commit a handle batch
+
+ @Input 	psBase	- handle base
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRReleaseHandleBatch
+
+ @Description	Release a handle batch
+
+ @Input 	psBase	- handle base
+
+ @Return	none
+
+******************************************************************************/
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	(IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSetMaxHandle
+
+ @Description	Set maximum handle number for given handle base
+
+ @Input 	psBase - pointer to handle base structure
+		ui32MaxHandle - Maximum handle number
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+	IMG_UINT32 ui32MaxHandleRounded;
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Validate the limit */
+	if (ui32MaxHandle  == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
+
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* The limit can only be set if no handles have been allocated */
+	if (psBase->ui32TotalHandCount != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
+
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
+
+	/*
+	 * Allow the maximum number of handles to be reduced, but never to
+	 * zero.
+	 */
+	if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
+	{
+		psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
+	}
+
+	PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0);
+	PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE);
+	PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0);
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetMaxHandle
+
+ @Description	Get maximum handle number for given handle base
+
+ @Input 	psBase - pointer to handle base structure
+
+ @Output 	Maximum handle number, or 0 if handle limits not
+		supported.
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+	return psBase->ui32MaxIndexPlusOne;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVEnableHandlePurging
+
+ @Description	Enable purging for a given handle base
+
+ @Input 	psBase - pointer to handle base structure
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+	if (psBase->bPurgingEnabled)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
+		return PVRSRV_OK;
+	}
+
+	/* Purging can only be enabled if no handles have been allocated */
+	if (psBase->ui32TotalHandCount != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psBase->bPurgingEnabled = IMG_TRUE;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPurgeHandles
+
+ @Description	Purge handles for a given handle base
+
+ @Input 	psBase - pointer to handle base structure
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+	IMG_UINT32 ui32BlockIndex;
+	IMG_UINT32 ui32NewHandCount;
+
+	if (!psBase->bPurgingEnabled)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+	}
+
+	if (HANDLES_BATCHED(psBase))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0);
+
+	for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
+	{
+		if (psBase->psHandleArray[ui32BlockIndex - 1].ui32FreeHandBlockCount != HANDLE_BLOCK_SIZE)
+		{
+			break;
+		}
+	}
+	ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
+
+	/*
+	 * Check for a suitable decrease in the handle count.
+	 */
+	if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
+	{
+		PVRSRV_ERROR eError;
+
+		// PVR_TRACE((" PVRSRVPurgeHandles: reducing number of handles from %u to %u", psBase->ui32TotalHandCount, ui32NewHandCount));
+
+		eError = ReallocHandleArray(psBase, ui32NewHandCount);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAllocHandleBase
+
+ @Description	Allocate a handle base structure for a process
+
+ @Input 	ppsBase - pointer to handle base structure pointer
+
+ @Output	ppsBase - points to handle base structure pointer
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+	PVRSRV_HANDLE_BASE *psBase;
+	IMG_HANDLE hBlockAlloc;
+	PVRSRV_ERROR eError;
+
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+		sizeof(*psBase),
+		(IMG_PVOID *)&psBase,
+		&hBlockAlloc,
+		"Handle Base");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
+		return eError;
+	}
+	OSMemSet(psBase, 0, sizeof(*psBase));
+
+	/* Create hash table */
+	psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
+	if (psBase->psHashTab == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
+		(IMG_VOID)PVRSRVFreeHandleBase(psBase);
+		return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+	}
+
+	psBase->hBaseBlockAlloc = hBlockAlloc;
+
+	psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
+
+	*ppsBase = psBase;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVFreeHandleBase
+
+ @Description	Free a handle base structure
+
+ @Input 	psBase - pointer to handle base structure
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(psBase != gpsKernelHandleBase);
+
+	eError = FreeHandleBase(psBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
+	}
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVHandleInit
+
+ @Description	Initialise handle management
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+
+	eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
+		goto error;
+	}
+
+	eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
+		goto error;
+	}
+
+	return PVRSRV_OK;
+error:
+	(IMG_VOID) PVRSRVHandleDeInit();
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVHandleDeInit
+
+ @Description	De-initialise handle management
+
+ @Return	Error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (gpsKernelHandleBase != IMG_NULL)
+	{
+		eError = FreeHandleBase(gpsKernelHandleBase);
+		if (eError == PVRSRV_OK)
+		{
+			gpsKernelHandleBase = IMG_NULL;
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
+		}
+	}
+
+	return eError;
+}
+#else
+/* disable warning about empty module */
+#endif	/* #if defined(PVR_SECURE_HANDLES) */
+/******************************************************************************
+ End of file (handle.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/hash.c b/drivers/gpu/pvr/services4/srvkm/common/hash.c
new file mode 100644
index 0000000..8dcedf9
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/hash.c
@@ -0,0 +1,739 @@
+/*************************************************************************/ /*!
+@Title          Self scaling hash tables.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description
+   Implements simple self scaling hash tables. Hash collisions are
+   handled by chaining entries together. Hash tables are increased in
+   size when they become more than (50%?) full and decreased in size
+   when less than (25%?) full. Hash tables are never decreased below
+   their initial size.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "pvr_debug.h"
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "hash.h"
+#include "osfunc.h"
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define	KEY_TO_INDEX(pHash, key, uSize) \
+	((pHash)->pfnHashFunc((pHash)->uKeySize, (key), (uSize)) % (uSize))
+
+#define	KEY_COMPARE(pHash, pKey1, pKey2) \
+	((pHash)->pfnKeyComp((pHash)->uKeySize, (pKey1), (pKey2)))
+
+/* Each entry in a hash table is placed into a bucket */
+struct _BUCKET_
+{
+	/* the next bucket on the same chain */
+	struct _BUCKET_ *pNext;
+
+	/* entry value */
+	IMG_UINTPTR_T v;
+
+	/* entry key */
+	IMG_UINTPTR_T k[];		/* PRQA S 0642 */ /* override dynamic array declaration warning */
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_
+{
+	/* the hash table array */
+	BUCKET **ppBucketTable;
+
+	/* current size of the hash table */
+	IMG_UINT32 uSize;
+
+	/* number of entries currently in the hash table */
+	IMG_UINT32 uCount;
+
+	/* the minimum size that the hash table should be re-sized to */
+	IMG_UINT32 uMinimumSize;
+
+	/* size of key in bytes */
+	IMG_UINT32 uKeySize;
+
+	/* hash function */
+	HASH_FUNC *pfnHashFunc;
+
+	/* key comparison function */
+	HASH_KEY_COMP *pfnKeyComp;
+};
+
+/*!
+******************************************************************************
+	@Function   	HASH_Func_Default
+
+	@Description    Hash function intended for hashing keys composed of
+                    IMG_UINTPTR_T arrays.
+
+	@Input          uKeySize - the size of the hash key, in bytes.
+	@Input          pKey - a pointer to the key to hash.
+	@Input          uHashTabLen - the length of the hash table.
+    
+	@Return 	    the hash value.
+******************************************************************************/
+IMG_UINT32
+HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
+{
+	IMG_UINTPTR_T *p = (IMG_UINTPTR_T *)pKey;
+	IMG_UINT32 uKeyLen = (IMG_UINT32)(uKeySize / sizeof(IMG_UINTPTR_T));
+	IMG_UINT32 ui;
+	IMG_UINT32 uHashKey = 0;
+
+	PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+	PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+	for (ui = 0; ui < uKeyLen; ui++)
+	{
+		IMG_UINT32 uHashPart = (IMG_UINT32)*p++;
+
+		uHashPart += (uHashPart << 12);
+		uHashPart ^= (uHashPart >> 22);
+		uHashPart += (uHashPart << 4);
+		uHashPart ^= (uHashPart >> 9);
+		uHashPart += (uHashPart << 10);
+		uHashPart ^= (uHashPart >> 2);
+		uHashPart += (uHashPart << 7);
+		uHashPart ^= (uHashPart >> 12);
+
+		uHashKey += uHashPart;
+	}
+
+	return uHashKey;
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Key_Comp_Default
+
+	@Description    Compares keys composed of IMG_UINTPTR_T arrays.
+
+	@Input          uKeySize - the size of the hash key, in bytes.
+	@Input          pKey1 - pointer to first hash key to compare.
+	@Input          pKey2 - pointer to second hash key to compare.
+	@Return 	    IMG_TRUE  - the keys match.
+                    IMG_FALSE - the keys don't match.
+******************************************************************************/
+IMG_BOOL
+HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
+{
+	IMG_UINTPTR_T *p1 = (IMG_UINTPTR_T *)pKey1;
+	IMG_UINTPTR_T *p2 = (IMG_UINTPTR_T *)pKey2;
+	IMG_UINT32 uKeyLen = (IMG_UINT32)(uKeySize / sizeof(IMG_UINTPTR_T));
+	IMG_UINT32 ui;
+
+	PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+	for (ui = 0; ui < uKeyLen; ui++)
+	{
+		if (*p1++ != *p2++)
+			return IMG_FALSE;
+	}
+
+	return IMG_TRUE;
+}
+
+/*!
+******************************************************************************
+	@Function   	_ChainInsert
+
+	@Description    Insert a bucket into the appropriate hash table chain.
+
+	@Input          pBucket - the bucket
+	@Input          ppBucketTable - the hash table
+	@Input          uSize - the size of the hash table
+    
+	@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
+{
+	IMG_UINT32 uIndex;
+
+	PVR_ASSERT (pBucket != IMG_NULL);
+	PVR_ASSERT (ppBucketTable != IMG_NULL);
+	PVR_ASSERT (uSize != 0);
+
+	if ((pBucket == IMG_NULL) || (ppBucketTable == IMG_NULL) || (uSize == 0))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);	/* PRQA S 0432,0541 */ /* ignore dynamic array warning */
+	pBucket->pNext = ppBucketTable[uIndex];
+	ppBucketTable[uIndex] = pBucket;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+	@Function   	_Rehash
+
+	@Description   	Iterate over every entry in an old hash table and
+                    rehash into the new table.
+
+	@Input          ppOldTable - the old hash table
+	@Input          uOldSize - the size of the old hash table
+	@Input          ppNewTable - the new hash table
+	@Input          uNewSize - the size of the new hash table
+    
+	@Return         None
+******************************************************************************/
+static PVRSRV_ERROR
+_Rehash (HASH_TABLE *pHash,
+	 BUCKET **ppOldTable, IMG_UINT32 uOldSize,
+         BUCKET **ppNewTable, IMG_UINT32 uNewSize)
+{
+	IMG_UINT32 uIndex;
+	for (uIndex=0; uIndex< uOldSize; uIndex++)
+    {
+		BUCKET *pBucket;
+		pBucket = ppOldTable[uIndex];
+		while (pBucket != IMG_NULL)
+		{
+			PVRSRV_ERROR eError;
+			BUCKET *pNextBucket = pBucket->pNext;
+			eError = _ChainInsert (pHash, pBucket, ppNewTable, uNewSize);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "_Rehash: call to _ChainInsert failed"));
+				return eError;
+			}
+			pBucket = pNextBucket;
+		}
+    }
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+	@Function   	_Resize
+
+	@Description    Attempt to resize a hash table, failure to allocate a
+                    new larger hash table is not considered a hard failure.
+                    We simply continue and allow the table to fill up, the
+	            	effect is to allow hash chains to become longer.
+
+	@Input          pHash - Hash table to resize.
+    @Input          uNewSize - Required table size.
+	@Return         IMG_TRUE Success
+	            	IMG_FALSE Failed
+******************************************************************************/
+static IMG_BOOL
+_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
+{
+	if (uNewSize != pHash->uSize)
+    {
+		BUCKET **ppNewTable;
+        IMG_UINT32 uIndex;
+
+		PVR_DPF ((PVR_DBG_MESSAGE,
+                  "HASH_Resize: oldsize=0x%x  newsize=0x%x  count=0x%x",
+				pHash->uSize, uNewSize, pHash->uCount));
+
+		OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                      sizeof (BUCKET *) * uNewSize,
+                      (IMG_PVOID*)&ppNewTable, IMG_NULL,
+					  "Hash Table Buckets");
+		if (ppNewTable == IMG_NULL)
+            return IMG_FALSE;
+
+        for (uIndex=0; uIndex<uNewSize; uIndex++)
+            ppNewTable[uIndex] = IMG_NULL;
+
+        if (_Rehash (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize) != PVRSRV_OK)
+		{
+			OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *) * uNewSize, ppNewTable, IMG_NULL);
+			return IMG_FALSE;
+		}
+
+        OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+        /*not nulling pointer, being reassigned just below*/
+        pHash->ppBucketTable = ppNewTable;
+        pHash->uSize = uNewSize;
+    }
+    return IMG_TRUE;
+}
+
+
+/*!
+******************************************************************************
+	@Function   	HASH_Create_Extended
+
+	@Description    Create a self scaling hash table, using the supplied
+                    key size, and the supplied hash and key comparsion
+                    functions.
+
+	@Input          uInitialLen - initial and minimum length of the
+                    hash table, where the length refers to the number
+                    of entries in the hash table, not its size in
+                    bytes.
+	@Input          uKeySize - the size of the key, in bytes.
+	@Input          pfnHashFunc - pointer to hash function.
+    @Input          pfnKeyComp - pointer to key comparsion function.
+	@Return         IMG_NULL or hash table handle.
+******************************************************************************/
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
+{
+	HASH_TABLE *pHash;
+	IMG_UINT32 uIndex;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x", uInitialLen));
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(HASH_TABLE),
+					(IMG_VOID **)&pHash, IMG_NULL,
+					"Hash Table") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	pHash->uCount = 0;
+	pHash->uSize = uInitialLen;
+	pHash->uMinimumSize = uInitialLen;
+	pHash->uKeySize = (IMG_UINT32)uKeySize;
+	pHash->pfnHashFunc = pfnHashFunc;
+	pHash->pfnKeyComp = pfnKeyComp;
+
+	OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+                  sizeof (BUCKET *) * pHash->uSize,
+                  (IMG_PVOID*)&pHash->ppBucketTable, IMG_NULL,
+				  "Hash Table Buckets");
+
+	if (pHash->ppBucketTable == IMG_NULL)
+    {
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+		return IMG_NULL;
+    }
+
+	for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+		pHash->ppBucketTable[uIndex] = IMG_NULL;
+	return pHash;
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Create
+
+	@Description    Create a self scaling hash table with a key
+                    consisting of a single IMG_UINTPTR_T, and using
+                    the default hash and key comparison functions.
+
+	@Input          uInitialLen - initial and minimum length of the
+                    hash table, where the length refers to the
+                    number of entries in the hash table, not its size
+                    in bytes.
+	@Return 	    IMG_NULL or hash table handle.
+******************************************************************************/
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
+{
+	return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
+		&HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+/*!
+******************************************************************************
+	@Function       HASH_Delete
+
+	@Description    Delete a hash table created by HASH_Create_Extended or
+                    HASH_Create.  All entries in the table must have been
+                    removed before calling this function.
+
+	@Input          pHash - hash table
+    
+	@Return 	    None
+******************************************************************************/
+IMG_VOID
+HASH_Delete (HASH_TABLE *pHash)
+{
+	if (pHash != IMG_NULL)
+    {
+		PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Delete"));
+
+		PVR_ASSERT (pHash->uCount==0);
+		if(pHash->uCount != 0)
+		{
+			PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
+			PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing allocations before destroying devmemcontext"));
+		}
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+		pHash->ppBucketTable = IMG_NULL;
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+    }
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Insert_Extended
+
+	@Description    Insert a key value pair into a hash table created
+                    with HASH_Create_Extended.
+
+	@Input          pHash - the hash table.
+	@Input          pKey - pointer to the key.
+	@Input          v - the value associated with the key.
+
+	@Return 	    IMG_TRUE  - success
+	            	IMG_FALSE  - failure
+******************************************************************************/
+IMG_BOOL
+HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
+{
+	BUCKET *pBucket;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Insert_Extended: Hash=0x%p, pKey=0x%p, v=0x" UINTPTR_FMT,
+              pHash, pKey, v));
+
+	PVR_ASSERT (pHash != IMG_NULL);
+
+	if (pHash == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "HASH_Insert_Extended: invalid parameter"));
+		return IMG_FALSE;
+	}
+
+	if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(BUCKET) + pHash->uKeySize,
+					(IMG_VOID **)&pBucket, IMG_NULL,
+					"Hash Table entry") != PVRSRV_OK)
+	{
+		return IMG_FALSE;
+	}
+
+	pBucket->v = v;
+	/* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k (linux)*/
+	OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+	if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
+	{
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+				  sizeof(BUCKET) + pHash->uKeySize,
+				  pBucket, IMG_NULL);
+		return IMG_FALSE;
+	}
+
+	pHash->uCount++;
+
+	/* check if we need to think about re-balencing */
+	if (pHash->uCount << 1 > pHash->uSize)
+    {
+        /* Ignore the return code from _Resize because the hash table is
+           still in a valid state and although not ideally sized, it is still
+           functional */
+        _Resize (pHash, pHash->uSize << 1);
+    }
+
+
+	return IMG_TRUE;
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Insert
+
+	@Description    Insert a key value pair into a hash table created with
+                    HASH_Create.
+
+	@Input          pHash - the hash table.
+	@Input          k - the key value.
+	@Input          v - the value associated with the key.
+
+	@Return 	    IMG_TRUE - success.
+	            	IMG_FALSE - failure.
+******************************************************************************/
+IMG_BOOL
+HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Insert: Hash=0x%p, k=0x" UINTPTR_FMT ", v=0x" UINTPTR_FMT,
+              pHash, k, v));
+
+	return HASH_Insert_Extended(pHash, &k, v);
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Remove_Extended
+
+	@Description    Remove a key from a hash table created with
+                    HASH_Create_Extended.
+
+	@Input          pHash - the hash table.
+	@Input          pKey - pointer to key.
+
+	@Return 	    0 if the key is missing, or the value associated
+                    with the key.
+******************************************************************************/
+IMG_UINTPTR_T
+HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+	BUCKET **ppBucket;
+	IMG_UINT32 uIndex;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove_Extended: Hash=0x%p, pKey=0x%p",
+			pHash, pKey));
+
+	PVR_ASSERT (pHash != IMG_NULL);
+
+	if (pHash == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "HASH_Remove_Extended: Null hash table"));
+		return 0;
+	}
+
+	uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+	for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+	{
+		/* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
+		if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+		{
+			BUCKET *pBucket = *ppBucket;
+			IMG_UINTPTR_T v = pBucket->v;
+			(*ppBucket) = pBucket->pNext;
+
+			OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
+			/*not nulling original pointer, already overwritten*/
+
+			pHash->uCount--;
+
+			/* check if we need to think about re-balencing */
+			if (pHash->uSize > (pHash->uCount << 2) &&
+                pHash->uSize > pHash->uMinimumSize)
+            {
+                /* Ignore the return code from _Resize because the
+                   hash table is still in a valid state and although
+                   not ideally sized, it is still functional */
+				_Resize (pHash,
+                         PRIVATE_MAX (pHash->uSize >> 1,
+                                      pHash->uMinimumSize));
+            }
+
+			PVR_DPF ((PVR_DBG_MESSAGE,
+                      "HASH_Remove_Extended: Hash=0x%p, pKey=0x%p = 0x" UINTPTR_FMT,
+                      pHash, pKey, v));
+			return v;
+		}
+	}
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Remove_Extended: Hash=0x%p, pKey=0x%p = 0x0 !!!!",
+              pHash, pKey));
+	return 0;
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Remove
+
+	@Description    Remove a key value pair from a hash table created
+                    with HASH_Create.
+
+	@Input          pHash - the hash table
+	@Input          k - the key
+
+	@Return         0 if the key is missing, or the value associated
+                    with the key.
+******************************************************************************/
+IMG_UINTPTR_T
+HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove: Hash=0x%p, k=0x" UINTPTR_FMT,
+			pHash, k));
+
+	return HASH_Remove_Extended(pHash, &k);
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Retrieve_Extended
+
+	@Description    Retrieve a value from a hash table created with
+                    HASH_Create_Extended.
+
+	@Input          pHash - the hash table.
+	@Input          pKey - pointer to the key.
+
+	@Return 	    0 if the key is missing, or the value associated with
+                    the key.
+******************************************************************************/
+IMG_UINTPTR_T
+HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+	BUCKET **ppBucket;
+	IMG_UINT32 uIndex;
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve_Extended: Hash=0x%p, pKey=0x%p",
+			pHash, pKey));
+
+	PVR_ASSERT (pHash != IMG_NULL);
+
+	if (pHash == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "HASH_Retrieve_Extended: Null hash table"));
+		return 0;
+	}
+
+	uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+	for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+	{
+		/* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
+		if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+		{
+			BUCKET *pBucket = *ppBucket;
+			IMG_UINTPTR_T v = pBucket->v;
+
+			PVR_DPF ((PVR_DBG_MESSAGE,
+                      "HASH_Retrieve: Hash=0x%p, pKey=0x%p = 0x" UINTPTR_FMT,
+                      pHash, pKey, v));
+			return v;
+		}
+	}
+	PVR_DPF ((PVR_DBG_MESSAGE,
+              "HASH_Retrieve: Hash=0x%p, pKey=0x%p = 0x0 !!!!",
+              pHash, pKey));
+	return 0;
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Retrieve
+
+	@Description    Retrieve a value from a hash table created with
+                    HASH_Create.
+
+	@Input          pHash - the hash table
+	@Input          k - the key
+	@Return 	    0 if the key is missing, or the value associated with
+                    the key.
+******************************************************************************/
+IMG_UINTPTR_T
+HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+	PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=0x%p, k=0x" UINTPTR_FMT,
+			pHash, k));
+	return HASH_Retrieve_Extended(pHash, &k);
+}
+
+/*!
+******************************************************************************
+	@Function   	HASH_Iterate
+
+	@Description    Iterate over every entry in the hash table
+
+	@Input          pHash - the old hash table
+	@Input          pfnCallback - the size of the old hash table
+
+	@Return 	    Callback error if any, otherwise PVRSRV_OK
+******************************************************************************/
+PVRSRV_ERROR
+HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback)
+{
+	IMG_UINT32 uIndex;
+	for (uIndex=0; uIndex < pHash->uSize; uIndex++)
+	{
+		BUCKET *pBucket;
+		pBucket = pHash->ppBucketTable[uIndex];
+		while (pBucket != IMG_NULL)
+		{
+			PVRSRV_ERROR eError;
+			BUCKET *pNextBucket = pBucket->pNext;
+			
+			eError = pfnCallback((IMG_UINTPTR_T) ((IMG_VOID *) *(pBucket->k)), (IMG_UINTPTR_T) pBucket->v);
+
+			/* The callback might want us to break out early */
+			if (eError != PVRSRV_OK)
+				return eError;
+
+			pBucket = pNextBucket;
+		}
+	}
+	return PVRSRV_OK;
+}
+
+#ifdef HASH_TRACE
+/*!
+******************************************************************************
+	@Function   	HASH_Dump
+
+	@Description   	To dump the contents of a hash table in human readable
+                    form.
+
+	@Input          pHash - the hash table
+
+	@Return 	    None
+******************************************************************************/
+IMG_VOID
+HASH_Dump (HASH_TABLE *pHash)
+{
+	IMG_UINT32 uIndex;
+	IMG_UINT32 uMaxLength=0;
+	IMG_UINT32 uEmptyCount=0;
+
+	PVR_ASSERT (pHash != IMG_NULL);
+	for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+	{
+		BUCKET *pBucket;
+		IMG_UINT32 uLength = 0;
+		if (pHash->ppBucketTable[uIndex] == IMG_NULL)
+		{
+			uEmptyCount++;
+		}
+		for (pBucket=pHash->ppBucketTable[uIndex];
+				pBucket != IMG_NULL;
+				pBucket = pBucket->pNext)
+		{
+			uLength++;
+		}
+		uMaxLength = PRIVATE_MAX (uMaxLength, uLength);
+	}
+
+	PVR_TRACE(("hash table: uMinimumSize=%d  size=%d  count=%d",
+			pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+	PVR_TRACE(("  empty=%d  max=%d", uEmptyCount, uMaxLength));
+}
+#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/common/lists.c b/drivers/gpu/pvr/services4/srvkm/common/lists.c
new file mode 100644
index 0000000..4ffdb0d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/lists.c
@@ -0,0 +1,159 @@
+/*************************************************************************/ /*!
+@Title          Linked list shared functions implementation
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implementation of the list iterators for types shared among
+                more than one file in the services code.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#include "lists.h"
+#include "services_headers.h"
+
+/*===================================================================
+  LIST ITERATOR FUNCTIONS USED IN MORE THAN ONE FILE (those used just
+  once are implemented locally).
+  ===================================================================*/
+
+IMPLEMENT_LIST_ANY_VA(BM_HEAP)
+IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH_VA(BM_HEAP)
+IMPLEMENT_LIST_REMOVE(BM_HEAP)
+IMPLEMENT_LIST_INSERT(BM_HEAP)
+
+IMPLEMENT_LIST_ANY_VA(BM_CONTEXT)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(BM_CONTEXT)
+IMPLEMENT_LIST_REMOVE(BM_CONTEXT)
+IMPLEMENT_LIST_INSERT(BM_CONTEXT)
+
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+
+IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+IMPLEMENT_LIST_ANY_2(PVRSRV_KERNEL_SYNC_INFO, PVRSRV_ERROR, PVRSRV_OK);
+IMPLEMENT_LIST_INSERT(PVRSRV_KERNEL_SYNC_INFO)
+IMPLEMENT_LIST_REMOVE(PVRSRV_KERNEL_SYNC_INFO)
+
+/*===================================================================
+  BELOW ARE IMPLEMENTED SOME COMMON CALLBACKS USED IN DIFFERENT FILES
+  ===================================================================*/
+
+
+/*!
+******************************************************************************
+	@Function   MatchDeviceKM_AnyVaCb
+	@Description Matchs a device node with an id and optionally a class.
+
+	@Input      psDeviceNode - Pointer to the device node.
+    @Input      va - Variable argument list, with te following values:
+					# ui32DevIndex - Index of de device to match.
+					# bIgnoreClass - Flag indicating if there's
+						no need to check the device class.
+					# eDevClass - Device class, ONLY present if
+						bIgnoreClass was IMG_FALSE.
+
+	@Return		The pointer to the device node if it matchs, IMG_NULL
+                otherwise.
+******************************************************************************/
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
+{
+	IMG_UINT32 ui32DevIndex;
+	IMG_BOOL bIgnoreClass;
+	PVRSRV_DEVICE_CLASS eDevClass;
+
+	ui32DevIndex = va_arg(va, IMG_UINT32);
+	bIgnoreClass = va_arg(va, IMG_BOOL);
+	if (!bIgnoreClass)
+	{
+		eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+	}
+	else
+	{
+		/*this value will never be used, since the short circuit evaluation
+		of the first clause will stop because bIgnoreClass is true, but the
+		compiler complains if it's not initialized.*/
+		eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+	}
+
+	if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+		psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+	{
+		return psDeviceNode;
+	}
+	return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+
+ @Function	MatchPowerDeviceIndex_AnyVaCb
+
+ @Description
+ 			Matches a power device with its device index.
+
+ @Input		va : variable argument list with:
+ 				ui32DeviceIndex : device index
+
+ @Return	the pointer to the device it matched, IMG_NULL otherwise.
+
+******************************************************************************/
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
+{
+	IMG_UINT32 ui32DeviceIndex;
+
+	ui32DeviceIndex = va_arg(va, IMG_UINT32);
+
+	if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
+	{
+		return psPowerDev;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/common/mem.c b/drivers/gpu/pvr/services4/srvkm/common/mem.c
new file mode 100644
index 0000000..cccdd24
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/mem.c
@@ -0,0 +1,175 @@
+/*************************************************************************/ /*!
+@Title          System memory functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    System memory allocation APIs
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+
+static PVRSRV_ERROR
+FreeSharedSysMemCallBack(IMG_PVOID  pvParam,
+						 IMG_UINT32 ui32Param,
+						 IMG_BOOL   bDummy)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	OSFreePages(psKernelMemInfo->ui32Flags,
+				psKernelMemInfo->uAllocSize,
+				psKernelMemInfo->pvLinAddrKM,
+				psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+			  sizeof(PVRSRV_KERNEL_MEM_INFO),
+			  psKernelMemInfo,
+			  IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+							 IMG_UINT32					ui32Flags,
+							 IMG_SIZE_T 				uSize,
+							 PVRSRV_KERNEL_MEM_INFO 	**ppsKernelMemInfo)
+{
+	PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO),
+				  (IMG_VOID **)&psKernelMemInfo, IMG_NULL,
+				  "Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo));
+
+	ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+	ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+	psKernelMemInfo->ui32Flags = ui32Flags;
+	psKernelMemInfo->uAllocSize = uSize;
+
+	if(OSAllocPages(psKernelMemInfo->ui32Flags,
+					psKernelMemInfo->uAllocSize,
+					(IMG_UINT32)HOST_PAGESIZE(),
+					IMG_NULL,
+					0,
+					IMG_NULL,
+					&psKernelMemInfo->pvLinAddrKM,
+					&psKernelMemInfo->sMemBlk.hOSMemHandle)
+		!= PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block"));
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO),
+				  psKernelMemInfo,
+				  0);
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* register with the resman */
+	psKernelMemInfo->sMemBlk.hResItem =
+				ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_SHARED_MEM_INFO,
+								  psKernelMemInfo,
+								  0,
+								  &FreeSharedSysMemCallBack);
+
+	*ppsKernelMemInfo = psKernelMemInfo;
+
+	return PVRSRV_OK; 
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVRSRV_ERROR eError;
+
+	if(psKernelMemInfo->sMemBlk.hResItem)
+	{
+		eError = ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+	}
+	else
+	{
+		eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0, CLEANUP_WITH_POLL);
+	}
+
+	return eError;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if(!psKernelMemInfo)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if(psKernelMemInfo->sMemBlk.hResItem)
+	{
+		eError = ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem, IMG_NULL);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVDissociateMemFromResmanKM: ResManDissociateRes failed"));
+			PVR_DBG_BREAK;
+			return eError;
+		}
+
+		psKernelMemInfo->sMemBlk.hResItem = IMG_NULL;
+	}
+
+	return eError;
+}
+
+/******************************************************************************
+ End of file (mem.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/mem_debug.c b/drivers/gpu/pvr/services4/srvkm/common/mem_debug.c
new file mode 100644
index 0000000..f79e7cb
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/mem_debug.c
@@ -0,0 +1,276 @@
+/*************************************************************************/ /*!
+@Title          Memory debugging routines.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Adds extra memory to the allocations to trace the memory bounds
+                and other runtime information.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef MEM_DEBUG_C
+#define MEM_DEBUG_C
+
+#if defined(PVRSRV_DEBUG_OS_MEMORY)
+
+#include "img_types.h"
+#include "services_headers.h"
+
+#if defined (__cplusplus)
+extern "C"
+{
+#endif
+
+#define STOP_ON_ERROR 0
+
+	/*
+	 Allocated Memory Layout:
+	 
+	 ---------                     \
+	 Status    [OSMEM_DEBUG_INFO]   |- TEST_BUFFER_PADDING_STATUS
+	 ---------                     <
+	 [0xBB]*   [raw bytes]          |- ui32Size 
+	 ---------                     <
+	 [0xB2]*   [raw bytes]          |- TEST_BUFFER_PADDING_AFTER
+	 ---------                     /
+	*/
+
+	IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
+	{
+		IMG_UINT8 *pui8Addr;
+		for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++)
+		{
+			if (*pui8Addr != ui8Pattern)
+			{
+				return IMG_FALSE;
+			}
+		}
+		return IMG_TRUE;
+	}
+
+	/*
+	This function expects the pointer to the user data, not the debug data.
+	*/
+	IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
+	{
+		OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINTPTR_T)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+		/* invalid pointer */
+		if (pvCpuVAddr == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : null pointer"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+		/* align */
+		if (((IMG_UINT32)pvCpuVAddr&3) != 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : invalid alignment"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+		/*check guard region before*/
+		if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : guard region before overwritten"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+		/*check size*/
+		if (uSize != psInfo->uSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING, 
+					"Pointer 0x%p : supplied size was different to stored size (0x%" 
+					SIZE_T_FMT_LEN "X != 0x%" SIZE_T_FMT_LEN "X)"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr, uSize, psInfo->uSize,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+
+		/*check size parity*/
+		if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING, 
+					"Pointer 0x%p : stored size parity error (0x%"
+					SIZE_T_FMT_LEN "X != 0x%" SIZE_T_FMT_LEN "X)"
+					 " - referenced %s:%d - allocated %s:%d",
+					 pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+		else
+		{
+			/*the stored size is ok, so we use it instead the supplied uSize*/
+			uSize = psInfo->uSize;
+		}
+
+		/*check padding after*/
+		if (uSize)
+		{
+			if (!MemCheck((IMG_VOID*)((IMG_UINTPTR_T)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : guard region after overwritten"
+						 " - referenced from %s:%d - allocated from %s:%d",
+						 pvCpuVAddr,
+						 pszFileName, uLine,
+						 psInfo->sFileName, psInfo->uLineNo));
+			}
+		}
+
+		/* allocated... */
+		if (psInfo->eValid != isAllocated)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%p : not allocated (freed? %d)"
+					 " - referenced %s:%d - freed %s:%d",
+					 pvCpuVAddr, psInfo->eValid == isFree,
+					 pszFileName, uLine,
+					 psInfo->sFileName, psInfo->uLineNo));
+			while (STOP_ON_ERROR);
+		}
+	}
+
+	IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc)
+	{
+		IMG_SIZE_T i = 0;
+
+		for (; i < 128; i++) /*changed to 128 to match the filename array size*/
+		{
+			*pDest = *pSrc;
+			if (*pSrc == '\0') break;
+			pDest++;
+			pSrc++;
+		}
+	}
+
+	PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+										  IMG_UINT32 ui32Size,
+										  IMG_PVOID *ppvCpuVAddr,
+										  IMG_HANDLE *phBlockAlloc,
+										  IMG_CHAR *pszFilename,
+										  IMG_UINT32 ui32Line)
+	{
+		OSMEM_DEBUG_INFO *psInfo;
+
+		PVRSRV_ERROR eError;
+
+		eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
+				 ui32Size + TEST_BUFFER_PADDING,
+				 ppvCpuVAddr,
+				 phBlockAlloc,
+				 pszFilename,
+				 ui32Line);
+
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+
+		OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
+		OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
+
+		/*fill the dbg info struct*/
+		psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
+
+		OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
+		debug_strcpy(psInfo->sFileName, pszFilename);
+		psInfo->uLineNo = ui32Line;
+		psInfo->eValid = isAllocated;
+		psInfo->uSize = ui32Size;
+		psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
+
+		/*point to the user data section*/
+		*ppvCpuVAddr = (IMG_PVOID) ((IMG_UINTPTR_T)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+		/*this is here to simplify the surounding logging macro, that is a expression
+		maybe the macro should be an expression */
+		PVR_TRACE(("Allocated pointer (after debug info): 0x%p from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
+#endif
+
+		return PVRSRV_OK;
+	}
+
+	PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+										 IMG_UINT32 ui32Size,
+										 IMG_PVOID pvCpuVAddr,
+										 IMG_HANDLE hBlockAlloc,
+										 IMG_CHAR *pszFilename,
+										 IMG_UINT32 ui32Line)
+	{
+		OSMEM_DEBUG_INFO *psInfo;
+
+		/*check dbginfo (arg pointing to user memory)*/
+		OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
+
+		/*mark memory as freed*/
+		OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+
+		/*point to the starting address of the total allocated memory*/
+		psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINTPTR_T) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+		/*update dbg info struct*/
+		psInfo->uSize = 0;
+		psInfo->uSizeParityCheck = 0;
+		psInfo->eValid = isFree;
+		psInfo->uLineNo = ui32Line;
+		debug_strcpy(psInfo->sFileName, pszFilename);
+
+		return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line);
+	}
+
+#if defined (__cplusplus)
+
+}
+#endif
+
+#endif /* PVRSRV_DEBUG_OS_MEMORY */
+
+#endif /* MEM_DEBUG_C */
diff --git a/drivers/gpu/pvr/services4/srvkm/common/metrics.c b/drivers/gpu/pvr/services4/srvkm/common/metrics.c
new file mode 100644
index 0000000..7370ec1
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/metrics.c
@@ -0,0 +1,209 @@
+/*************************************************************************/ /*!
+@Title          Time measuring functions.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "metrics.h"
+
+/* VGX: */
+#if defined(SUPPORT_VGX)
+#include "vgxapi_km.h"
+#endif
+
+/* SGX: */
+#if defined(SUPPORT_SGX)
+#include "sgxapi_km.h"
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+static volatile IMG_UINT32 *pui32TimerRegister = 0;
+
+#define PVRSRV_TIMER_TOTAL_IN_TICKS(X)	asTimers[X].ui32Total
+#define PVRSRV_TIMER_TOTAL_IN_MS(X)		((1000*asTimers[X].ui32Total)/ui32TicksPerMS)
+#define PVRSRV_TIMER_COUNT(X)			asTimers[X].ui32Count
+
+
+Temporal_Data asTimers[PVRSRV_NUM_TIMERS]; 
+
+
+/***********************************************************************************
+ Function Name      : PVRSRVTimeNow
+ Inputs             : None
+ Outputs            : None
+ Returns            : Current timer register value
+ Description        : Returns the current timer register value
+************************************************************************************/
+IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
+{
+	if (!pui32TimerRegister)
+	{
+		static IMG_BOOL bFirstTime = IMG_TRUE;
+
+		if (bFirstTime)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVTimeNow: No timer register set up"));
+
+			bFirstTime = IMG_FALSE;
+		}
+
+		return 0;
+	}
+
+#if defined(__sh__)
+
+	return (0xffffffff-*pui32TimerRegister);
+
+#else /* defined(__sh__) */
+
+	return 0;
+
+#endif /* defined(__sh__) */
+}
+
+
+/***********************************************************************************
+ Function Name      : PVRSRVGetCPUFreq
+ Inputs             : None
+ Outputs            : None
+ Returns            : CPU timer frequency
+ Description        : Returns the CPU timer frequency
+************************************************************************************/
+static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
+{
+	IMG_UINT32 ui32Time1, ui32Time2;
+
+	ui32Time1 = PVRSRVTimeNow();
+
+	OSWaitus(1000000);
+
+	ui32Time2 = PVRSRVTimeNow();
+
+	PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetCPUFreq: timer frequency = %d Hz", ui32Time2 - ui32Time1));
+
+	return (ui32Time2 - ui32Time1);
+}
+
+
+/***********************************************************************************
+ Function Name      : PVRSRVSetupMetricTimers
+ Inputs             : pvDevInfo
+ Outputs            : None
+ Returns            : None
+ Description        : Resets metric timers and sets up the timer register
+************************************************************************************/
+IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
+{
+	IMG_UINT32 ui32Loop;
+
+	PVR_UNREFERENCED_PARAMETER(pvDevInfo);
+
+	for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+	{
+		asTimers[ui32Loop].ui32Total = 0;
+		asTimers[ui32Loop].ui32Count = 0;
+	}
+
+	#if defined(__sh__)
+
+		/* timer control register */
+		// clock / 1024 when TIMER_DIVISOR = 4
+		// underflow int disabled
+		// we get approx 38 uS per timer tick 
+		*TCR_2 = TIMER_DIVISOR;
+
+		/* reset the timer counter to 0 */
+		*TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
+
+		/* start timer 2 */
+		*TST_REG |= (IMG_UINT8)0x04;
+
+		pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
+
+	#else /* defined(__sh__) */
+
+		pui32TimerRegister = 0;
+
+	#endif /* defined(__sh__) */
+}
+
+
+/***********************************************************************************
+ Function Name      : PVRSRVOutputMetricTotals
+ Inputs             : None
+ Outputs            : None
+ Returns            : None
+ Description        : Displays final metric data
+************************************************************************************/
+IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
+{
+	IMG_UINT32 ui32TicksPerMS, ui32Loop;
+
+	ui32TicksPerMS = PVRSRVGetCPUFreq();
+
+	if (!ui32TicksPerMS)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVOutputMetricTotals: Failed to get CPU Freq"));
+		return;
+	}
+
+	for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+	{
+		if (asTimers[ui32Loop].ui32Count & 0x80000000L)
+		{
+			PVR_DPF((PVR_DBG_WARNING,"PVRSRVOutputMetricTotals: Timer %u is still ON", ui32Loop));
+		}
+	}
+#if 0
+	/*
+	** EXAMPLE TIMER OUTPUT
+	*/
+	PVR_DPF((PVR_DBG_ERROR," Timer(%u): Total = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
+	PVR_DPF((PVR_DBG_ERROR," Timer(%u): Time = %ums",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
+	PVR_DPF((PVR_DBG_ERROR," Timer(%u): Count = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
+#endif
+}
+
+#endif /* defined(DEBUG) || defined(TIMING) */
+
+/******************************************************************************
+ End of file (metrics.c)
+******************************************************************************/
+
diff --git a/drivers/gpu/pvr/services4/srvkm/common/osfunc_common.c b/drivers/gpu/pvr/services4/srvkm/common/osfunc_common.c
new file mode 100644
index 0000000..19ba9ea
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/osfunc_common.c
@@ -0,0 +1,48 @@
+/*************************************************************************/ /*!
+@Title          Wrapper layer for osfunc routines that have common code.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Adds extra memory to the allocations to trace the memory bounds
+                and other runtime information.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "osfunc.h"
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/common/pdump_common.c b/drivers/gpu/pvr/services4/srvkm/common/pdump_common.c
new file mode 100644
index 0000000..af56752
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/pdump_common.c
@@ -0,0 +1,3117 @@
+/*************************************************************************/ /*!
+@Title          Common PDump functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if defined(PDUMP)
+#include <stdarg.h>
+
+#include "services_headers.h"
+#include "perproc.h"
+
+/* pdump headers */
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+/* Allow temporary buffer size override */
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024U)
+#endif
+
+/* DEBUG */
+#if 1
+#define PDUMP_DBG(a)   PDumpOSDebugPrintf (a)
+#else
+#define PDUMP_DBG(a)
+#endif
+
+
+#define	PTR_PLUS(t, p, x) ((t)(((IMG_CHAR *)(p)) + (x)))
+#define	VPTR_PLUS(p, x) PTR_PLUS(IMG_VOID *, p, x)
+#define	VPTR_INC(p, x) ((p) = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS	(32)
+static IMG_VOID *gpvTempBuffer = IMG_NULL;
+static IMG_HANDLE ghTempBufferBlockAlloc;
+static IMG_UINT16 gui16MMUContextUsage = 0;
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
+IMG_UINT32 g_ui32EveryLineCounter = 1U;
+#endif
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+
+IMG_BOOL _PDumpIsProcessActive(IMG_VOID)
+{
+	PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+	if(psPerProc == IMG_NULL)
+	{
+		return IMG_FALSE;
+	}
+	return psPerProc->bPDumpActive;
+}
+
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+static INLINE
+IMG_UINT32 _PDumpGetPID(IMG_VOID)
+{
+	PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+	if(psPerProc == IMG_NULL)
+	{
+		/* Kernel PID */
+		return 0;
+	}
+	return psPerProc->ui32PID;
+}
+#endif /* PDUMP_DEBUG_OUTFILES */
+
+/**************************************************************************
+ * Function Name  : GetTempBuffer
+ * Inputs         : None
+ * Outputs        : None
+ * Returns        : Temporary buffer address, or IMG_NULL
+ * Description    : Get temporary buffer address.
+**************************************************************************/
+static IMG_VOID *GetTempBuffer(IMG_VOID)
+{
+	/*
+	 * Allocate the temporary buffer, it it hasn't been allocated already.
+	 * Return the address of the temporary buffer, or IMG_NULL if it
+	 * couldn't be allocated.
+	 * It is expected that the buffer will be allocated once, at driver
+	 * load time, and left in place until the driver unloads.
+	 */
+
+	if (gpvTempBuffer == IMG_NULL)
+	{
+		PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  PDUMP_TEMP_BUFFER_SIZE,
+					  &gpvTempBuffer,
+					  &ghTempBufferBlockAlloc,
+					  "PDUMP Temporary Buffer");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "GetTempBuffer: OSAllocMem failed: %d", eError));
+		}
+	}
+
+	return gpvTempBuffer;
+}
+
+static IMG_VOID FreeTempBuffer(IMG_VOID)
+{
+
+	if (gpvTempBuffer != IMG_NULL)
+	{
+		PVRSRV_ERROR eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+					  PDUMP_TEMP_BUFFER_SIZE,
+					  gpvTempBuffer,
+					  ghTempBufferBlockAlloc);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreeTempBuffer: OSFreeMem failed: %d", eError));
+		}
+		else
+		{
+			gpvTempBuffer = IMG_NULL;
+		}
+	}
+}
+
+IMG_VOID PDumpInitCommon(IMG_VOID)
+{
+	/* Allocate temporary buffer for copying from user space */
+	(IMG_VOID) GetTempBuffer();
+
+	/* Call environment specific PDump initialisation */
+	PDumpInit();
+}
+
+IMG_VOID PDumpDeInitCommon(IMG_VOID)
+{
+	/* Free temporary buffer */
+	FreeTempBuffer();
+
+	/* Call environment specific PDump Deinitialisation */
+	PDumpDeInit();
+}
+
+IMG_BOOL PDumpIsSuspended(IMG_VOID)
+{
+	return PDumpOSIsSuspended();
+}
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	if( _PDumpIsProcessActive() )
+	{
+		return PDumpOSIsCaptureFrameKM();
+	}
+	return IMG_FALSE;
+#else
+	return PDumpOSIsCaptureFrameKM();
+#endif
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	if( _PDumpIsProcessActive() )
+	{
+		return PDumpOSSetFrameKM(ui32Frame);
+	}
+	return PVRSRV_OK;
+#else
+	return PDumpOSSetFrameKM(ui32Frame);
+#endif
+}
+
+static IMG_BOOL _PDumpWillCapture(IMG_UINT32 ui32Flags)
+{
+	/*
+		FIXME:
+		We really need to know if the PDump client is connected so we can
+		check if the continuous data will be saved or not.
+	*/
+	if ((ui32Flags & PDUMP_FLAGS_PERSISTENT) || (ui32Flags & PDUMP_FLAGS_CONTINUOUS))
+	{
+		return IMG_TRUE;
+	}
+	else
+	{
+		return PDumpIsCaptureFrameKM();
+	}
+}
+
+IMG_BOOL PDumpWillCapture(IMG_UINT32 ui32Flags)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	if( _PDumpIsProcessActive() )
+	{
+		return _PDumpWillCapture(ui32Flags);
+	}
+	return PVRSRV_OK;
+#else
+	return _PDumpWillCapture(ui32Flags);
+#endif
+}
+
+/**************************************************************************
+ * Function Name  : PDumpRegWithFlagsKM
+ * Inputs         : pszPDumpDevName, Register offset, and value to write
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Create a PDUMP string, which represents a register write
+**************************************************************************/
+PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+								IMG_UINT32 ui32Reg,
+								IMG_UINT32 ui32Data,
+								IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING()
+
+	PDUMP_LOCK();
+	PDUMP_DBG(("PDumpRegWithFlagsKM"));
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :%s:0x%08X 0x%08X\r\n",
+								pszPDumpRegName, ui32Reg, ui32Data);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpRegKM
+ * Inputs         : Register offset, and value to write
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Create a PDUMP string, which represents a register write
+**************************************************************************/
+PVRSRV_ERROR PDumpRegKM(IMG_CHAR *pszPDumpRegName,
+						IMG_UINT32 ui32Reg,
+						IMG_UINT32 ui32Data)
+{
+	return PDumpRegWithFlagsKM(pszPDumpRegName, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
+}
+
+/**************************************************************************
+ * Function Name  : PDumpRegPolWithFlagsKM
+ * Inputs         : Description of what this register read is trying to do
+ *					pszPDumpDevName
+ *					Register offset
+ *					expected value
+ *					mask for that value
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Create a PDUMP string which represents a register read
+ *					with the expected value
+**************************************************************************/
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+									IMG_UINT32 ui32RegAddr, 
+									IMG_UINT32 ui32RegValue, 
+									IMG_UINT32 ui32Mask,
+									IMG_UINT32 ui32Flags,
+									PDUMP_POLL_OPERATOR	eOperator)
+{
+	/* Timings correct for linux and XP */
+	#define POLL_DELAY			1000U
+	#define POLL_COUNT_LONG		(2000000000U / POLL_DELAY)
+	#define POLL_COUNT_SHORT	(1000000U / POLL_DELAY)
+
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32PollCount;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
+
+	ui32PollCount = POLL_COUNT_LONG;
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :%s:0x%08X 0x%08X 0x%08X %d %u %d\r\n",
+							pszPDumpRegName, ui32RegAddr, ui32RegValue,
+							ui32Mask, eOperator, ui32PollCount, POLL_DELAY);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name  : PDumpRegPol
+ * Inputs         : Description of what this register read is trying to do
+ *					pszPDumpDevName
+ 					Register offset
+ *					expected value
+ *					mask for that value
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Create a PDUMP string which represents a register read
+ *					with the expected value
+**************************************************************************/
+PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask, PDUMP_POLL_OPERATOR	eOperator)
+{
+	return PDumpRegPolWithFlagsKM(pszPDumpRegName, ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS, eOperator);
+}
+
+/**************************************************************************
+ * Function Name  : PDumpMallocPages
+ * Inputs         : psDevID, ui32DevVAddr, pvLinAddr, ui32NumBytes, hOSMemHandle
+ *                : hUniqueTag
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Malloc memory pages
+
+FIXME: This function assumes pvLinAddr is the address of the start of the 
+block for this hOSMemHandle.
+If this isn't true, the call to PDumpOSCPUVAddrToDevPAddr below will be 
+incorrect.  (Consider using OSMemHandleToCPUPAddr() instead?)
+The only caller at the moment is in buffer_manager.c, which does the right
+thing.
+**************************************************************************/
+PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER	*psDevID,
+                           IMG_UINT32         ui32DevVAddr,
+                           IMG_CPU_VIRTADDR   pvLinAddr,
+                           IMG_HANDLE         hOSMemHandle,
+                           IMG_UINT32         ui32NumBytes,
+                           IMG_UINT32         ui32PageSize,
+                           IMG_HANDLE         hUniqueTag,
+                           IMG_UINT32		  ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	IMG_PUINT8		pui8LinAddr;
+    IMG_UINT32      ui32Offset;
+	IMG_UINT32		ui32NumPages;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	IMG_UINT32		ui32Page;
+	IMG_UINT32		ui32PageSizeShift = 0;
+	IMG_UINT32		ui32PageSizeTmp;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+
+	/* However, lin addr is only required in non-linux OSes */
+#if !defined(LINUX)
+	PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PageSize -1)) == 0);
+#endif
+
+	PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & (ui32PageSize -1)) == 0);
+	PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (ui32PageSize -1)) == 0);
+
+	/*
+	   Compute the amount to right-shift in order to divide by the page-size.
+	   Required for 32-bit PAE kernels (thus phys addresses are 64-bits) where
+	   64-bit division is unsupported.
+	 */
+	ui32PageSizeTmp = ui32PageSize;
+	while (ui32PageSizeTmp >>= 1)
+		ui32PageSizeShift++;
+
+	/*
+		Write a comment to the PDump2 script streams indicating the memory allocation
+	*/
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :%s:VA_%08X 0x%08X %u (%d pages)\r\n",
+			psDevID->pszPDumpDevName, ui32DevVAddr, ui32NumBytes, ui32PageSize, ui32NumBytes / ui32PageSize);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	/*
+		Write to the MMU script stream indicating the memory allocation
+	*/
+	pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+	ui32Offset = 0;
+	ui32NumPages = ui32NumBytes >> ui32PageSizeShift;
+	while (ui32NumPages)
+	{ 
+		ui32NumPages--;
+
+		/* See FIXME in function header. 
+		 * Currently:  linux pdump uses OSMemHandle and Offset 
+		 *             other OSes use the LinAddr. 
+		 */
+ 		/* Calculate the device physical address for this page */
+		PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+				hOSMemHandle,
+				ui32Offset,
+				pui8LinAddr,
+				ui32PageSize,
+				&sDevPAddr);
+		ui32Page = (IMG_UINT32)(sDevPAddr.uiAddr >> ui32PageSizeShift);
+		/* increment kernel virtual address */
+		pui8LinAddr	+= ui32PageSize;
+		ui32Offset += ui32PageSize;
+
+		sDevPAddr.uiAddr = ui32Page * ui32PageSize;
+
+		eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_" UINTPTR_FMT DEVPADDR_FMT " %u %u 0x" DEVPADDR_FMT "\r\n",
+												psDevID->pszPDumpDevName,
+												(IMG_UINTPTR_T)hUniqueTag,
+												sDevPAddr.uiAddr,
+												ui32PageSize,
+												ui32PageSize,
+												sDevPAddr.uiAddr);
+		if(eErr != PVRSRV_OK)
+		{
+			PDUMP_UNLOCK();
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, ui32Flags);
+	}
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name  : PDumpMallocPageTable
+ * Inputs         : psDevId, pvLinAddr, ui32NumBytes, hUniqueTag
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Malloc memory page table
+**************************************************************************/
+PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER	*psDevId,
+								   IMG_HANDLE hOSMemHandle,
+								   IMG_UINT32 ui32Offset,
+                              	   IMG_CPU_VIRTADDR pvLinAddr,
+								   IMG_UINT32 ui32PTSize,
+								   IMG_UINT32 ui32Flags,
+								   IMG_HANDLE hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize - 1)) == 0);
+
+	ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+
+	/*
+		Write a comment to the PDump2 script streams indicating the memory allocation
+	*/
+	eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLen,
+							"-- MALLOC :%s:PAGE_TABLE 0x%08X %u\r\n",
+							psDevId->pszPDumpDevName,
+							ui32PTSize,
+							ui32PTSize);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	/*
+		Write to the MMU script stream indicating the memory allocation
+	*/
+	// FIXME: we'll never need more than a 4k page for a pagetable
+	// fixing to 1 page for now.
+	// note: when the mmu code supports packed pagetables the PTs
+	// will be as small as 16bytes
+
+	PDumpOSCPUVAddrToDevPAddr(psDevId->eDeviceType,
+			hOSMemHandle, /* um - does this mean the pvLinAddr would be ignored?  Is that safe? */
+			ui32Offset,
+			(IMG_PUINT8) pvLinAddr,
+			ui32PTSize,
+			&sDevPAddr);
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_" UINTPTR_FMT DEVPADDR_FMT 
+												 " 0x%X %u 0x" DEVPADDR_FMT "\r\n",
+											psDevId->pszPDumpDevName,
+											(IMG_UINTPTR_T)hUniqueTag,
+											sDevPAddr.uiAddr,
+											ui32PTSize,//size
+											ui32PTSize,//alignment
+											sDevPAddr.uiAddr);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpFreePages
+ * Inputs         : psBMHeap, sDevVAddr, ui32NumBytes, hUniqueTag,
+ 					bInterLeaved
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Free memory pages
+**************************************************************************/
+PVRSRV_ERROR PDumpFreePages	(BM_HEAP 			*psBMHeap,
+                         IMG_DEV_VIRTADDR  sDevVAddr,
+                         IMG_UINT32        ui32NumBytes,
+                         IMG_UINT32        ui32PageSize,
+                         IMG_HANDLE        hUniqueTag,
+						 IMG_BOOL		   bInterleaved,
+						 IMG_BOOL		   bSparse,
+						 IMG_UINT32		   ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32NumPages, ui32PageCounter;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	PVR_ASSERT(((IMG_UINT32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+	PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+	psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+	/*
+		Write a comment to the PDUMP2 script streams indicating the memory free
+	*/
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:VA_%08X\r\n", 
+							psDeviceNode->sDevId.pszPDumpDevName, sDevVAddr.uiAddr);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	/*
+		Write to the MMU script stream indicating the memory free
+	*/
+	ui32NumPages = ui32NumBytes / ui32PageSize;
+	for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
+	{
+		if (!bInterleaved || (ui32PageCounter % 2) == 0)
+		{
+			sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
+
+			/* With sparse mappings we expect spaces */
+			if (bSparse && (sDevPAddr.uiAddr == 0))
+			{
+				continue;
+			}
+
+			PVR_ASSERT(sDevPAddr.uiAddr != 0);
+
+			eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_" UINTPTR_FMT DEVPADDR_FMT "\r\n",
+									psDeviceNode->sDevId.pszPDumpDevName, 
+                                    (IMG_UINTPTR_T)hUniqueTag, 
+                                    sDevPAddr.uiAddr);
+			if(eErr != PVRSRV_OK)
+			{
+				PDUMP_UNLOCK();
+				return eErr;
+			}
+			PDumpOSWriteString2(hScript, ui32Flags);
+		}
+		else
+		{
+			/* Gap pages in an interleaved allocation should be ignored. */
+		}
+
+		sDevVAddr.uiAddr += ui32PageSize;
+	}
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpFreePageTable
+ * Inputs         : psDevID, pvLinAddr, ui32NumBytes, hUniqueTag
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Free memory page table
+**************************************************************************/
+PVRSRV_ERROR PDumpFreePageTable	(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+								 IMG_HANDLE hOSMemHandle,
+								 IMG_CPU_VIRTADDR   pvLinAddr,
+								 IMG_UINT32         ui32PTSize,
+								 IMG_UINT32			ui32Flags,
+								 IMG_HANDLE         hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_DEV_PHYADDR	sDevPAddr;
+	PDUMP_GET_SCRIPT_STRING();
+	PVR_UNREFERENCED_PARAMETER(ui32PTSize);
+
+	PDUMP_LOCK();
+
+	/* override QAC warning about wrap around */
+	PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0);	/* PRQA S 3382 */
+
+	/*
+		Write a comment to the PDUMP2 script streams indicating the memory free
+	*/
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:PAGE_TABLE\r\n", psDevID->pszPDumpDevName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	/*
+		Write to the MMU script stream indicating the memory free
+	*/
+	// FIXME: we'll never need more than a 4k page for a pagetable
+	// fixing to 1 page for now.
+	// note: when the mmu code supports packed pagetables the PTs
+	// will be as small as 16bytes
+
+	PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+							  hOSMemHandle, /* um - does this mean the pvLinAddr would be ignored?  Is that safe? */
+			0,
+			(IMG_PUINT8) pvLinAddr,
+			ui32PTSize,
+			&sDevPAddr);
+
+	{
+		eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_" UINTPTR_FMT DEVPADDR_FMT "\r\n",
+								psDevID->pszPDumpDevName,
+								(IMG_UINTPTR_T)hUniqueTag,
+								sDevPAddr.uiAddr);
+		if(eErr != PVRSRV_OK)
+		{
+			PDUMP_UNLOCK();
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, ui32Flags);
+	}
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpPDRegWithFlags
+ * Inputs         : psMMUAttrib
+ *				  : ui32Reg
+ *				  : ui32Data
+ *				  : hUniqueTag
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Kernel Services internal pdump memory API
+ *					Used for registers specifying physical addresses
+ 					e.g. MMU page directory register
+**************************************************************************/
+PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+							IMG_UINT32 ui32Reg,
+							 IMG_UINT32 ui32Data,
+							 IMG_UINT32	ui32Flags,
+							 IMG_HANDLE hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_CHAR *pszRegString;
+	IMG_DEV_PHYADDR sDevPAddr;
+
+	PDUMP_GET_SCRIPT_STRING()
+
+	PDUMP_LOCK();
+	if(psMMUAttrib->pszPDRegRegion != IMG_NULL)
+	{	
+		pszRegString = psMMUAttrib->pszPDRegRegion;
+	}
+	else
+	{
+		pszRegString = psMMUAttrib->sDevId.pszPDumpRegName;
+	}
+
+	/*
+		Write to the MMU script stream indicating the physical page directory
+	*/
+#if defined(SGX_FEATURE_36BIT_MMU)
+	sDevPAddr.uiAddr = ((ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift);
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+			 "WRW :%s:$1 :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X\r\n",
+			 psMMUAttrib->sDevId.pszPDumpDevName,
+			 psMMUAttrib->sDevId.pszPDumpDevName,
+			 (IMG_UINTPTR_T)hUniqueTag,
+			 sDevPAddr.uiAddr,
+			 ui32Data & ~psMMUAttrib->ui32PDEMask);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :%s:$1 :%s:$1 0x4\r\n", 
+			psMMUAttrib->sDevId.pszPDumpDevName,
+			psMMUAttrib->sDevId.pszPDumpDevName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+			 "WRW :%s:0x%08X: %s:$1\r\n",
+			 pszRegString,
+			 ui32Reg,
+			 psMMUAttrib->sDevId.pszPDumpDevName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+#else
+	sDevPAddr.uiAddr = ((ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift);
+
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				"WRW :%s:0x%08X :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X\r\n",
+				pszRegString,
+				ui32Reg,
+				psMMUAttrib->sDevId.pszPDumpDevName,
+				(IMG_UINTPTR_T)hUniqueTag,
+				sDevPAddr.uiAddr,
+				ui32Data & ~psMMUAttrib->ui32PDEMask);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+#endif
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpPDReg
+ * Inputs         : psMMUAttrib
+ 				  : ui32Reg
+ *				  : ui32Data
+ *				  : hUniqueTag
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Kernel Services internal pdump memory API
+ *					Used for registers specifying physical addresses
+ 					e.g. MMU page directory register
+**************************************************************************/
+PVRSRV_ERROR PDumpPDReg	(PDUMP_MMU_ATTRIB *psMMUAttrib, 
+					 IMG_UINT32 ui32Reg,
+					 IMG_UINT32 ui32Data,
+					 IMG_HANDLE hUniqueTag)
+{
+	return PDumpPDRegWithFlags(psMMUAttrib, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+}
+
+/**************************************************************************
+ * Function Name  : PDumpMemPolKM
+ * Inputs         : psMemInfo
+ *				  : ui32Offset
+ *				  : ui32Value
+ *				  : ui32Mask
+ *				  : eOperator
+ *				  : ui32Flags
+ *				  : hUniqueTag
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Implements Client pdump memory poll API
+**************************************************************************/
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO		*psMemInfo,
+						   IMG_UINT32			ui32Offset,
+						   IMG_UINT32			ui32Value,
+						   IMG_UINT32			ui32Mask,
+						   PDUMP_POLL_OPERATOR	eOperator,
+						   IMG_UINT32			ui32Flags,
+						   IMG_HANDLE			hUniqueTag)
+{
+	#define MEMPOLL_DELAY		(1000)
+	#define MEMPOLL_COUNT		(2000000000 / MEMPOLL_DELAY)
+
+	PVRSRV_ERROR eErr;
+	IMG_UINT32			ui32PageOffset;
+	IMG_UINT8			*pui8LinAddr;
+	IMG_DEV_PHYADDR		sDevPAddr;
+	IMG_DEV_VIRTADDR	sDevVPageAddr;
+	PDUMP_MMU_ATTRIB	*psMMUAttrib;
+
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	if (PDumpOSIsSuspended())
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_OK;
+	}
+
+	/* Check the offset and size don't exceed the bounds of the allocation */
+	PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->uAllocSize);
+
+	psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+	/*
+		Write a comment to the PDump2 script streams indicating the virtual memory pol
+	*/
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "-- POL :%s:VA_%08X 0x%08X 0x%08X %d %d %d\r\n",
+			 psMMUAttrib->sDevId.pszPDumpDevName,
+			 psMemInfo->sDevVAddr.uiAddr + ui32Offset,
+			 ui32Value,
+			 ui32Mask,
+			 eOperator,
+			 MEMPOLL_COUNT,
+			 MEMPOLL_DELAY);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+
+	pui8LinAddr = psMemInfo->pvLinAddrKM;
+
+	/* Advance address by offset */
+	pui8LinAddr += ui32Offset;
+
+	/*
+		query the buffer manager for the physical pages that back the
+		virtual address
+	*/
+	PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+			ui32Offset,
+			pui8LinAddr,
+			psMMUAttrib->ui32DataPageMask,
+			&ui32PageOffset);
+
+	/* calculate the DevV page address */
+	sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+	PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+
+	/* get the physical page address based on the device virtual address */
+	BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+	/* convert DevP page address to byte address */
+	sDevPAddr.uiAddr += ui32PageOffset;
+
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "POL :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X 0x%08X 0x%08X %d %d %d\r\n",
+			 psMMUAttrib->sDevId.pszPDumpDevName,
+			 (IMG_UINTPTR_T)hUniqueTag,
+			 sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+			 (unsigned int)(sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask)),
+			 ui32Value,
+			 ui32Mask,
+			 eOperator,
+			 MEMPOLL_COUNT,
+			 MEMPOLL_DELAY);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : _PDumpMemIntKM
+ * Inputs         : psMemInfo
+ *				  : ui32Offset
+ *				  : ui32Bytes
+ *				  : ui32Flags
+ *				  : hUniqueTag
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Implements Client pdump mem API
+**************************************************************************/
+static PVRSRV_ERROR _PDumpMemIntKM(IMG_PVOID pvAltLinAddr,
+								   PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								   IMG_UINT32 ui32Offset,
+								   IMG_UINT32 ui32PhyOffset,
+								   IMG_UINT32 ui32Bytes,
+								   IMG_UINT32 ui32Flags,
+								   IMG_HANDLE hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32NumPages;
+	IMG_UINT32 ui32PageByteOffset;
+	IMG_UINT32 ui32BlockBytes;
+	IMG_UINT8* pui8LinAddr;
+	IMG_UINT8* pui8DataLinAddr = IMG_NULL;
+	IMG_DEV_VIRTADDR sDevVPageAddr;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+	IMG_UINT32 ui32ParamOutPos;
+	PDUMP_MMU_ATTRIB *psMMUAttrib;
+	IMG_UINT32 ui32DataPageSize;
+	PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+	PDUMP_LOCK();
+	/* PRQA S 3415 1 */ /* side effects desired */
+	if (ui32Bytes == 0 || PDumpOSIsSuspended())
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_OK;
+	}
+
+	psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+	
+	/*
+		check the offset and size don't exceed the bounds of the allocation
+	*/
+	PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->uAllocSize);
+
+	if (!PDumpOSJTInitialised())
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+	}
+
+	/* setup memory addresses */
+	if(pvAltLinAddr)
+	{
+		pui8DataLinAddr = pvAltLinAddr;
+	}
+	else if(psMemInfo->pvLinAddrKM)
+	{
+		pui8DataLinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM + ui32Offset;
+	}
+	pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
+	sDevVAddr = psMemInfo->sDevVAddr;
+
+	/* advance address by offset */
+	sDevVAddr.uiAddr += ui32Offset;
+	pui8LinAddr += ui32Offset;
+
+	PVR_ASSERT(pui8DataLinAddr);
+
+	PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+	ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+	/*
+		write the binary data up-front.
+	*/
+	if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+						pui8DataLinAddr,
+						ui32Bytes,
+						ui32Flags))
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+	}
+
+	if (PDumpOSGetParamFileNum() == 0)
+	{
+		eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+	}
+	else
+	{
+		eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+	}
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	/*
+		Write a comment to the PDump2 script streams indicating the virtual memory load
+	*/
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLenScript,
+			 "-- LDB :%s:VA_" UINTPTR_FMT "%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+			 psMMUAttrib->sDevId.pszPDumpDevName,
+			 (IMG_UINTPTR_T)hUniqueTag,
+			 psMemInfo->sDevVAddr.uiAddr,
+			 ui32Offset,
+			 ui32Bytes,
+			 ui32ParamOutPos,
+			 pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	/*
+		query the buffer manager for the physical pages that back the
+		virtual address
+	*/
+
+	if (psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE)
+	{
+		PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+				ui32PhyOffset,
+				pui8LinAddr,
+				psMMUAttrib->ui32DataPageMask,
+				&ui32PageByteOffset);
+	}
+	else
+	{
+		PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+				ui32Offset,
+				pui8LinAddr,
+				psMMUAttrib->ui32DataPageMask,
+				&ui32PageByteOffset);
+	}
+	ui32DataPageSize = psMMUAttrib->ui32DataPageMask + 1;
+	ui32NumPages = (ui32PageByteOffset + ui32Bytes + psMMUAttrib->ui32DataPageMask) / ui32DataPageSize;
+
+	while(ui32NumPages)
+	{
+		ui32NumPages--;
+	
+		/* calculate the DevV page address */
+		sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+
+		if (ui32DataPageSize <= PDUMP_TEMP_BUFFER_SIZE)
+		{
+			/* if a page fits within temp buffer, we should dump in page-aligned chunks. */
+			PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+		}
+
+		/* get the physical page address based on the device virtual address */
+		BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+		/* convert DevP page address to byte address */
+		sDevPAddr.uiAddr += ui32PageByteOffset;
+
+		/* how many bytes to dump from this page */
+		if (ui32PageByteOffset + ui32Bytes > ui32DataPageSize)
+		{
+			/* dump up to the page boundary */
+			ui32BlockBytes = ui32DataPageSize - ui32PageByteOffset;
+		}
+		else
+		{
+			/* dump what's left */
+			ui32BlockBytes = ui32Bytes;
+		}
+
+		eErr = PDumpOSBufprintf(hScript,
+					 ui32MaxLenScript,
+					 "LDB :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X 0x%08X 0x%08X %s\r\n",
+					 psMMUAttrib->sDevId.pszPDumpDevName,
+					 (IMG_UINTPTR_T)hUniqueTag,
+					 sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+					 (unsigned int)(sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask)),
+					 ui32BlockBytes,
+					 ui32ParamOutPos,
+					 pszFileName);
+		if(eErr != PVRSRV_OK)
+		{
+			PDUMP_UNLOCK();
+			return eErr;
+		}
+		PDumpOSWriteString2(hScript, ui32Flags);
+
+		/* update details for next page */
+
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+		/* page may be larger than pdump temporary buffer */
+		ui32PageByteOffset = (ui32PageByteOffset + ui32BlockBytes) % ui32DataPageSize;
+#else
+		/* page offset 0 after first page dump */
+		ui32PageByteOffset = 0;
+#endif
+		/* bytes left over */
+		ui32Bytes -= ui32BlockBytes;	/* PRQA S 3382 */ /* QAC missed MIN test */
+		/* advance devVaddr */
+		sDevVAddr.uiAddr += ui32BlockBytes;
+		/* advance the cpuVaddr */
+		pui8LinAddr += ui32BlockBytes;
+		/* update the file write offset */
+		ui32ParamOutPos += ui32BlockBytes;
+	}
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpMemKM
+ * Inputs         : psMemInfo
+ *				  : ui32Offset
+ *				  : ui32Bytes
+ *				  : ui32Flags
+ *				  : hUniqueTag
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Implements Client pdump mem API
+**************************************************************************/
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+						PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+						IMG_UINT32 ui32Offset,
+						IMG_UINT32 ui32Bytes,
+						IMG_UINT32 ui32Flags,
+						IMG_HANDLE hUniqueTag)
+{
+	/*
+		For now we don't support dumping sparse allocations that
+		are from within the kernel, or are from UM but without a
+		alternative linear address
+	*/
+	PVR_ASSERT((psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE) == 0);
+
+	if (psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	else
+	{
+		return _PDumpMemIntKM(pvAltLinAddr,
+							  psMemInfo,
+							  ui32Offset,
+							  0,
+							  ui32Bytes,
+							  ui32Flags,
+							  hUniqueTag);
+	}
+}
+
+PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+								 IMG_HANDLE hOSMemHandle,
+								 IMG_CPU_VIRTADDR pvLinAddr,
+								 IMG_UINT32 ui32Bytes,
+								 IMG_UINT32 ui32Flags,
+								 IMG_BOOL bInitialisePages,
+								 IMG_HANDLE hUniqueTag1,
+								 IMG_HANDLE hUniqueTag2)
+{
+	PDUMP_MMU_ATTRIB sMMUAttrib;
+	
+	/* Override the (variable) PT size since PDs are always 4K in size */
+	sMMUAttrib = *psMMUAttrib;
+	sMMUAttrib.ui32PTSize = (IMG_UINT32)HOST_PAGESIZE();
+	return PDumpMemPTEntriesKM(	&sMMUAttrib,
+								hOSMemHandle,
+								pvLinAddr,
+								ui32Bytes,
+								ui32Flags,
+								bInitialisePages,
+								hUniqueTag1,
+								hUniqueTag2);
+}
+
+/**************************************************************************
+ * Function Name  : PDumpMemPTEntriesKM
+ * Inputs         : psMMUAttrib - MMU attributes for pdump
+ *				  : pvLinAddr - CPU address of PT base
+ *				  : ui32Bytes - size
+ *				  : ui32Flags - pdump flags
+ *				  : bInitialisePages - whether to initialise pages from file
+ *				  : hUniqueTag1 - ID for PT physical page
+ *				  : hUniqueTag2 - ID for target physical page (if !bInitialisePages)
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Kernel Services internal pdump memory API
+ *					Used for memory without DevVAddress mappings
+ 					e.g. MMU page tables
+ 					FIXME: This function doesn't support non-4k data pages,
+ 					e.g. dummy data page
+**************************************************************************/
+PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+								 IMG_HANDLE hOSMemHandle,
+								 IMG_CPU_VIRTADDR pvLinAddr,
+								 IMG_UINT32 ui32Bytes,
+								 IMG_UINT32 ui32Flags,
+								 IMG_BOOL bInitialisePages,
+								 IMG_HANDLE hUniqueTag1,
+								 IMG_HANDLE hUniqueTag2)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32NumPages;
+	IMG_UINT32 ui32PageOffset;
+	IMG_UINT32 ui32BlockBytes;
+	IMG_UINT8* pui8LinAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+	IMG_DEV_PHYADDR sDevPAddrTmp;
+	IMG_CPU_PHYADDR sCpuPAddr;
+	IMG_UINT32 ui32Offset;
+	IMG_UINT32 ui32ParamOutPos;
+	IMG_UINT32 ui32PageMask; /* mask for the physical page backing the PT */
+
+#if !defined(SGX_FEATURE_36BIT_MMU)
+	IMG_DEV_PHYADDR sDevPAddrTmp2;
+#endif
+	PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+	PDUMP_LOCK();
+
+
+	if (PDumpOSIsSuspended())
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_OK;
+	}
+
+	if (!PDumpOSJTInitialised())
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+	}
+
+	if (!pvLinAddr)
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+	ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+	if (bInitialisePages)
+	{
+		/*
+			write the binary data up-front
+			Use the 'continuous' memory stream
+		*/
+		if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+							pvLinAddr,
+							ui32Bytes,
+							ui32Flags | PDUMP_FLAGS_CONTINUOUS))
+		{
+			PDUMP_UNLOCK();
+			return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+		}
+
+		if (PDumpOSGetParamFileNum() == 0)
+		{
+			eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+		}
+		else
+		{
+			eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+		}
+		if(eErr != PVRSRV_OK)
+		{
+			PDUMP_UNLOCK();
+			return eErr;
+		}
+	}
+
+	/*
+		Mask for the physical page address backing the PT
+		The PT size can be less than 4k with variable page size support
+		The PD size is always 4k
+		FIXME: This won't work for dumping the dummy data page
+	*/
+	ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+	/*
+		Write to the MMU script stream indicating the physical page table entries
+	*/
+	/* physical pages that back the virtual address	*/
+ 	ui32PageOffset	= (IMG_UINT32)((IMG_UINTPTR_T)pvLinAddr & (psMMUAttrib->ui32PTSize - 1));
+ 	ui32NumPages	= (ui32PageOffset + ui32Bytes + psMMUAttrib->ui32PTSize - 1) / psMMUAttrib->ui32PTSize;
+	pui8LinAddr		= (IMG_UINT8*) pvLinAddr;
+
+	while (ui32NumPages)
+	{
+		ui32NumPages--;
+		/* FIXME: if we used OSMemHandleToCPUPAddr() here, we might be
+		   able to lose the lin addr arg.  At least one thing that
+		   would need to be done here is to pass in an offset, as the
+		   calling function doesn't necessarily give us the lin addr
+		   of the start of the mem area.  Probably best to keep the
+		   lin addr arg for now - but would be nice to remove the
+		   redundancy */
+		sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+		sDevPAddr = SysCpuPAddrToDevPAddr(psMMUAttrib->sDevId.eDeviceType, sCpuPAddr);
+
+		/* how many bytes to dump from this page */
+		if (ui32PageOffset + ui32Bytes > psMMUAttrib->ui32PTSize)
+		{
+			/* dump up to the page boundary */
+			ui32BlockBytes = psMMUAttrib->ui32PTSize - ui32PageOffset;
+		}
+		else
+		{
+			/* dump what's left */
+			ui32BlockBytes = ui32Bytes;
+		}
+
+		/*
+			Write a comment to the MMU script stream indicating the page table load
+		*/
+		
+		if (bInitialisePages)
+		{
+			eErr = PDumpOSBufprintf(hScript,
+					 ui32MaxLenScript,
+					 "LDB :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X 0x%08X 0x%08X %s\r\n",
+					 psMMUAttrib->sDevId.pszPDumpDevName,
+					 (IMG_UINTPTR_T)hUniqueTag1,
+					 sDevPAddr.uiAddr & ~ui32PageMask,
+					 (unsigned int)(sDevPAddr.uiAddr & ui32PageMask),
+					 ui32BlockBytes,
+					 ui32ParamOutPos,
+					 pszFileName);
+			if(eErr != PVRSRV_OK)
+			{
+				PDUMP_UNLOCK();
+				return eErr;
+			}
+			PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+		}
+		else
+		{
+			for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
+			{
+				IMG_UINT32 ui32PTE = *((IMG_UINT32 *)(IMG_UINTPTR_T)(pui8LinAddr + ui32Offset)); /* PRQA S 3305 */ /* strict pointer */
+
+				if ((ui32PTE & psMMUAttrib->ui32PDEMask) != 0)
+				{
+					/* PT entry points to non-null page */
+#if defined(SGX_FEATURE_36BIT_MMU)
+					sDevPAddrTmp.uiAddr = ((ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift);
+
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :%s:$1 :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x0\r\n",
+							 psMMUAttrib->sDevId.pszPDumpDevName,
+							 psMMUAttrib->sDevId.pszPDumpDevName,
+							 (IMG_UINTPTR_T)hUniqueTag2,
+							 sDevPAddrTmp.uiAddr);
+					if(eErr != PVRSRV_OK)
+					{
+						PDUMP_UNLOCK();
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+					eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$1 :%s:$1 0x4\r\n",
+								psMMUAttrib->sDevId.pszPDumpDevName,
+								psMMUAttrib->sDevId.pszPDumpDevName);
+					if(eErr != PVRSRV_OK)
+					{
+						PDUMP_UNLOCK();
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+					eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "OR :%s:$1 :%s:$1 0x%08X\r\n",
+								psMMUAttrib->sDevId.pszPDumpDevName,
+								psMMUAttrib->sDevId.pszPDumpDevName,
+								ui32PTE & ~psMMUAttrib->ui32PDEMask);
+					if(eErr != PVRSRV_OK)
+					{
+						PDUMP_UNLOCK();
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+					sDevPAddrTmp.uiAddr = (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask;
+
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X :%s:$1\r\n",
+							 psMMUAttrib->sDevId.pszPDumpDevName,
+							 (IMG_UINTPTR_T)hUniqueTag1,
+							 sDevPAddrTmp.uiAddr,
+							 (unsigned int)((sDevPAddr.uiAddr + ui32Offset) & ui32PageMask),
+							 psMMUAttrib->sDevId.pszPDumpDevName);
+					if(eErr != PVRSRV_OK)
+					{
+						PDUMP_UNLOCK();
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#else
+					sDevPAddrTmp.uiAddr  = (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask;
+					sDevPAddrTmp2.uiAddr = (ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift;
+
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X\r\n",
+							 psMMUAttrib->sDevId.pszPDumpDevName,
+							 (IMG_UINTPTR_T)hUniqueTag1,
+							 sDevPAddrTmp.uiAddr,
+							 (unsigned int)((sDevPAddr.uiAddr + ui32Offset) & ui32PageMask),
+							 psMMUAttrib->sDevId.pszPDumpDevName,
+							 (IMG_UINTPTR_T)hUniqueTag2,
+							 sDevPAddrTmp2.uiAddr,
+							 (unsigned int)(ui32PTE & ~psMMUAttrib->ui32PDEMask));
+					if(eErr != PVRSRV_OK)
+					{
+						PDUMP_UNLOCK();
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#endif
+				}
+				else
+				{
+#if !defined(FIX_HW_BRN_31620)
+					PVR_ASSERT((ui32PTE & psMMUAttrib->ui32PTEValid) == 0UL);
+#endif
+					sDevPAddrTmp.uiAddr = (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask;
+
+					eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLenScript,
+							 "WRW :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X 0x%08X" UINTPTR_FMT "\r\n",
+							 psMMUAttrib->sDevId.pszPDumpDevName,
+							 (IMG_UINTPTR_T)hUniqueTag1,
+							 sDevPAddrTmp.uiAddr,
+							 (unsigned int)((sDevPAddr.uiAddr + ui32Offset) & ui32PageMask),
+							 ui32PTE << psMMUAttrib->ui32PTEAlignShift,
+							 (IMG_UINTPTR_T)hUniqueTag2);
+					if(eErr != PVRSRV_OK)
+					{
+						PDUMP_UNLOCK();
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+				}
+			}
+		}
+
+		/* update details for next page */
+
+		/* page offset 0 after first page dump */
+		ui32PageOffset = 0;
+		/* bytes left over */
+		ui32Bytes -= ui32BlockBytes;
+		/* advance the cpuVaddr */
+		pui8LinAddr += ui32BlockBytes;
+		/* update the file write offset */
+		ui32ParamOutPos += ui32BlockBytes;
+	}
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+							   IMG_UINT32 ui32Offset,
+							   IMG_DEV_PHYADDR sPDDevPAddr,
+							   IMG_HANDLE hUniqueTag1,
+							   IMG_HANDLE hUniqueTag2)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32 ui32PageByteOffset;
+	IMG_DEV_VIRTADDR sDevVAddr;
+	IMG_DEV_VIRTADDR sDevVPageAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+	IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+	IMG_UINT32 ui32ParamOutPos;
+	PDUMP_MMU_ATTRIB *psMMUAttrib;
+	IMG_UINT32 ui32PageMask; /* mask for the physical page backing the PT */
+	IMG_DEV_PHYADDR sDevPAddrTmp;
+
+	PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+	PDUMP_LOCK();
+	if (!PDumpOSJTInitialised())
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+	}
+
+	psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+	ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+	ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+	/* Write the PD phys addr to the param stream up front */
+	if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+						(IMG_UINT8 *)&sPDDevPAddr,
+						sizeof(IMG_DEV_PHYADDR),
+						ui32Flags))
+	{
+		PDUMP_UNLOCK();
+		return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+	}
+
+	if (PDumpOSGetParamFileNum() == 0)
+	{
+		eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+	}
+	else
+	{
+		eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+	}
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	/* Write a comment indicating the PD phys addr write, so that the offsets
+	 * into the param stream increase in correspondence with the number of bytes
+	 * written. */
+	sDevPAddrTmp.uiAddr = sPDDevPAddr.uiAddr & ~ui32PageMask;
+
+	eErr = PDumpOSBufprintf(hScript,
+			ui32MaxLenScript,
+			"-- LDB :%s:PA_0x" UINTPTR_FMT DEVPADDR_FMT ":0x%08X 0x%08" SIZE_T_FMT_LEN "X 0x%08X %s\r\n",
+			psMMUAttrib->sDevId.pszPDumpDevName,
+			(IMG_UINTPTR_T)hUniqueTag1,
+			sDevPAddrTmp.uiAddr,
+			(unsigned int)(sPDDevPAddr.uiAddr & ui32PageMask),
+			sizeof(IMG_DEV_PHYADDR),
+			ui32ParamOutPos,
+			pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	sDevVAddr = psMemInfo->sDevVAddr;
+	ui32PageByteOffset = sDevVAddr.uiAddr & ui32PageMask;
+
+	sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+	PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+	BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+	sDevPAddr.uiAddr += ui32PageByteOffset + ui32Offset;
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+	sDevPAddrTmp.uiAddr = sPDDevPAddr.uiAddr & ~ui32PageMask;
+
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLenScript,
+				 "WRW :%s:$1 :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X\r\n",
+				 psMMUAttrib->sDevId.pszPDumpDevName,
+				 psMMUAttrib->sDevId.pszPDumpDevName,
+				 (IMG_UINTPTR_T)hUniqueTag2,
+				 sDevPAddrTmp.uiAddr,
+				 (unsigned int)(sPDDevPAddr.uiAddr & ui32PageMask));
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$1 :%s:$1 0x4\r\n",
+				psMMUAttrib->sDevId.pszPDumpDevName,
+				psMMUAttrib->sDevId.pszPDumpDevName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	PDumpOSWriteString2(hScript, ui32Flags);
+	sDevPAddrTmp.uiAddr = sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask);
+
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLenScript,
+				 "WRW :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X :%s:$1\r\n",
+				 psMMUAttrib->sDevId.pszPDumpDevName,
+				 (IMG_UINTPTR_T)hUniqueTag1,
+				 sDevPAddrTmp.uiAddr,
+				 (unsigned int)((sDevPAddr.uiAddr) & (psMMUAttrib->ui32DataPageMask)),
+				 psMMUAttrib->sDevId.pszPDumpDevName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+#else
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLenScript,
+				"WRW :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X \r\n",
+				psMMUAttrib->sDevId.pszPDumpDevName,
+				(IMG_UINTPTR_T)hUniqueTag1,
+				sDevPAddr.uiAddr & ~ui32PageMask,
+				(unsigned int)(sDevPAddr.uiAddr & ui32PageMask),
+				psMMUAttrib->sDevId.pszPDumpDevName,
+				(IMG_UINTPTR_T)hUniqueTag2,
+				sPDDevPAddr.uiAddr & psMMUAttrib->ui32PDEMask,
+				(unsigned int)(sPDDevPAddr.uiAddr & ~psMMUAttrib->ui32PDEMask));
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+#endif
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpCommentKM
+ * Inputs         : pszComment, ui32Flags
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Dumps a comment
+**************************************************************************/
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	IMG_CHAR pszCommentPrefix[] = "-- "; /* prefix for comments */
+#if defined(PDUMP_DEBUG_OUTFILES)
+	IMG_CHAR pszTemp[256];
+#endif
+	IMG_UINT32 ui32LenCommentPrefix;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	PDUMP_DBG(("PDumpCommentKM"));
+
+	/* Put \r \n sequence at the end if it isn't already there */
+	PDumpOSVerifyLineEnding(pszComment, ui32MaxLen);
+
+	/* Length of string excluding terminating NULL character */
+	ui32LenCommentPrefix = PDumpOSBuflen(pszCommentPrefix, sizeof(pszCommentPrefix));
+
+	/* Ensure output file is available for writing */
+	/* FIXME: is this necessary? */
+	if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_SCRIPT2),
+			  (IMG_UINT8*)pszCommentPrefix,
+			  ui32LenCommentPrefix,
+			  ui32Flags))
+	{
+#if defined(PDUMP_DEBUG_OUTFILES)
+		if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %d: %s (continuous set)",
+					 g_ui32EveryLineCounter, pszComment));
+			PDUMP_UNLOCK();
+			return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+		}
+		else if(ui32Flags & PDUMP_FLAGS_PERSISTENT)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %d: %s (persistent set)",
+					 g_ui32EveryLineCounter, pszComment));
+			PDUMP_UNLOCK();
+			return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %d: %s",
+					 g_ui32EveryLineCounter, pszComment));
+			PDUMP_UNLOCK();
+			return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+		}
+#else
+		PVR_DPF((PVR_DBG_WARNING, "Incomplete comment, %s",
+					 pszComment));
+		PDUMP_UNLOCK();
+		return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+#endif
+	}
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+	/* Prefix comment with PID and line number */
+	eErr = PDumpOSSprintf(pszTemp, 256, "%d-%d %s",
+		_PDumpGetPID(),
+		g_ui32EveryLineCounter,
+		pszComment);
+
+	/* Append the comment to the script stream */
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+		pszTemp);
+#else
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+		pszComment);
+#endif
+	if( (eErr != PVRSRV_OK) &&
+		(eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW))
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpCommentWithFlags
+ * Inputs         : psPDev - PDev for PDump device
+ *				  : pszFormat - format string for comment
+ *				  : ... - args for format string
+ * Outputs        : None
+ * Returns        : None
+ * Description    : PDumps a comments
+**************************************************************************/
+PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_va_list ap;
+	PDUMP_GET_MSG_STRING();
+
+	PDUMP_LOCK_MSG();
+	/* Construct the string */
+	PDUMP_va_start(ap, pszFormat);
+	eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+	PDUMP_va_end(ap);
+
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK_MSG();
+		return eErr;
+	}
+	eErr = PDumpCommentKM(pszMsg, ui32Flags);
+	PDUMP_UNLOCK_MSG();
+	return eErr;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpComment
+ * Inputs         : psPDev - PDev for PDump device
+ *				  : pszFormat - format string for comment
+ *				  : ... - args for format string
+ * Outputs        : None
+ * Returns        : None
+ * Description    : PDumps a comments
+**************************************************************************/
+PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_va_list ap;
+	PDUMP_GET_MSG_STRING();
+
+	PDUMP_LOCK_MSG();
+	/* Construct the string */
+	PDUMP_va_start(ap, pszFormat);
+	eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+	PDUMP_va_end(ap);
+
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK_MSG();
+		return eErr;
+	}
+	eErr = PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
+	PDUMP_UNLOCK_MSG();
+	return eErr;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpDriverInfoKM
+ * Inputs         : pszString, ui32Flags
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Dumps a comment
+**************************************************************************/
+PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32MsgLen;
+	PDUMP_GET_MSG_STRING();
+
+	PDUMP_LOCK_MSG();
+	/* Construct the string */
+	eErr = PDumpOSSprintf(pszMsg, ui32MaxLen, "%s", pszString);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK_MSG();
+		return eErr;
+	}
+
+	/* Put \r \n sequence at the end if it isn't already there */
+	PDumpOSVerifyLineEnding(pszMsg, ui32MaxLen);
+	ui32MsgLen = PDumpOSBuflen(pszMsg, ui32MaxLen);
+
+	if	(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_DRIVERINFO),
+						  (IMG_UINT8*)pszMsg,
+						  ui32MsgLen,
+						  ui32Flags))
+	{
+		if	(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+		{
+			PDUMP_UNLOCK_MSG();
+			return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+		}
+		else
+		{
+			PDUMP_UNLOCK_MSG();
+			return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+		}
+	}
+
+	PDUMP_UNLOCK_MSG();
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PDumpBitmapKM
+
+ @Description
+
+ Dumps a bitmap from device memory to a file
+
+ @Input    psDevId
+ @Input    pszFileName
+ @Input    ui32FileOffset
+ @Input    ui32Width
+ @Input    ui32Height
+ @Input    ui32StrideInBytes
+ @Input    sDevBaseAddr
+ @Input    ui32Size
+ @Input    ePixelFormat
+ @Input    eMemFormat
+ @Input    ui32PDumpFlags
+
+ @Return   PVRSRV_ERROR			:
+
+******************************************************************************/
+PVRSRV_ERROR PDumpBitmapKM(	PVRSRV_DEVICE_NODE *psDeviceNode,
+							IMG_CHAR *pszFileName,
+							IMG_UINT32 ui32FileOffset,
+							IMG_UINT32 ui32Width,
+							IMG_UINT32 ui32Height,
+							IMG_UINT32 ui32StrideInBytes,
+							IMG_DEV_VIRTADDR sDevBaseAddr,
+							IMG_HANDLE hDevMemContext,
+							IMG_UINT32 ui32Size,
+							PDUMP_PIXEL_FORMAT ePixelFormat,
+							PDUMP_MEM_FORMAT eMemFormat,
+							IMG_UINT32 ui32PDumpFlags)
+{
+	PVRSRV_DEVICE_IDENTIFIER *psDevId = &psDeviceNode->sDevId;
+	IMG_UINT32 ui32MMUContextID;
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
+
+	PDUMP_LOCK();
+	/* find MMU context ID */
+	ui32MMUContextID = psDeviceNode->pfnMMUGetContextID( hDevMemContext );
+
+	eErr = PDumpOSBufprintf(hScript,
+				ui32MaxLen,
+				"SII %s %s.bin :%s:v%x:0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+				pszFileName,
+				pszFileName,
+				psDevId->pszPDumpDevName,
+				ui32MMUContextID,
+				sDevBaseAddr.uiAddr,
+				ui32Size,
+				ui32FileOffset,
+				ePixelFormat,
+				ui32Width,
+				ui32Height,
+				ui32StrideInBytes,
+				eMemFormat);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	PDumpOSWriteString2( hScript, ui32PDumpFlags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PDumpReadRegKM
+
+ @Description
+
+ Dumps a read from a device register to a file
+
+ @Input    psConnection 		: connection info
+ @Input    pszFileName
+ @Input    ui32FileOffset
+ @Input    ui32Address
+ @Input    ui32Size
+ @Input    ui32PDumpFlags
+
+ @Return   PVRSRV_ERROR			:
+
+******************************************************************************/
+PVRSRV_ERROR PDumpReadRegKM		(	IMG_CHAR *pszPDumpRegName,
+									IMG_CHAR *pszFileName,
+									IMG_UINT32 ui32FileOffset,
+									IMG_UINT32 ui32Address,
+									IMG_UINT32 ui32Size,
+									IMG_UINT32 ui32PDumpFlags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+	PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+	PDUMP_LOCK();
+	eErr = PDumpOSBufprintf(hScript,
+			ui32MaxLen,
+			"SAB :%s:0x%08X 0x%08X %s\r\n",
+			pszPDumpRegName,
+			ui32Address,
+			ui32FileOffset,
+			pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	PDumpOSWriteString2( hScript, ui32PDumpFlags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name		PDumpTestNextFrame
+ @brief		Tests whether the next frame will be pdumped
+ @param		ui32CurrentFrame
+ @return	bFrameDumped
+*****************************************************************************/
+IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
+{
+	IMG_BOOL	bFrameDumped;
+
+	/*
+		Try dumping a string
+	*/
+	(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
+	bFrameDumped = PDumpIsCaptureFrameKM();
+	(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
+
+	return bFrameDumped;
+}
+
+/*****************************************************************************
+ @name		PDumpSignatureRegister
+ @brief		Dumps a single signature register
+ @param 	psDevId - device ID
+ @param 	ui32Address	- The register address
+ @param		ui32Size - The amount of data to be dumped in bytes
+ @param		pui32FileOffset - Offset of dump in output file
+ @param		ui32Flags - Flags
+ @return	none
+*****************************************************************************/
+static PVRSRV_ERROR PDumpSignatureRegister	(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+									 IMG_CHAR	*pszFileName,
+									 IMG_UINT32		ui32Address,
+									 IMG_UINT32		ui32Size,
+									 IMG_UINT32		*pui32FileOffset,
+									 IMG_UINT32		ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	eErr = PDumpOSBufprintf(hScript,
+			ui32MaxLen,
+			"SAB :%s:0x%08X 0x%08X %s\r\n",
+			psDevId->pszPDumpRegName,
+			ui32Address,
+			*pui32FileOffset,
+			pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	PDumpOSWriteString2(hScript, ui32Flags);
+	*pui32FileOffset += ui32Size;
+
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name		PDumpRegisterRange
+ @brief		Dumps a list of signature registers to a file
+ @param		psDevId - device ID
+ @param		pszFileName - target filename for dump
+ @param		pui32Registers - register list
+ @param		ui32NumRegisters - number of regs to dump
+ @param		pui32FileOffset - file offset
+ @param		ui32Size - size of write in bytes
+ @param		ui32Flags - pdump flags
+ @return	none
+ *****************************************************************************/
+static IMG_VOID PDumpRegisterRange(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+									IMG_CHAR *pszFileName,
+									IMG_UINT32 *pui32Registers,
+									IMG_UINT32  ui32NumRegisters,
+									IMG_UINT32 *pui32FileOffset,
+									IMG_UINT32	ui32Size,
+									IMG_UINT32	ui32Flags)
+{
+	IMG_UINT32 i;
+	for (i = 0; i < ui32NumRegisters; i++)
+	{
+		PDumpSignatureRegister(psDevId, pszFileName, pui32Registers[i], ui32Size, pui32FileOffset, ui32Flags);
+	}
+}
+
+/*****************************************************************************
+ @name		PDump3DSignatureRegisters
+ @brief		Dumps the signature registers for 3D modules...
+ @param		psDevId - device ID info
+ @param		pui32Registers - register list
+ @param		ui32NumRegisters - number of regs to dump
+ @return	Error
+*****************************************************************************/
+PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+										IMG_UINT32 ui32DumpFrameNum,
+										IMG_BOOL bLastFrame,
+										IMG_UINT32 *pui32Registers,
+										IMG_UINT32 ui32NumRegisters)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32FileOffset, ui32Flags;
+	PDUMP_GET_FILE_STRING();
+
+	ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+	ui32FileOffset = 0;
+
+	PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump 3D signature registers\r\n");
+	eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_3d.sig", ui32DumpFrameNum);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	/*
+		Note:
+		PDumpCommentWithFlags will take the lock so we defer the lock
+		taking until here
+	*/
+	PDUMP_LOCK();
+	PDumpRegisterRange(psDevId,
+						pszFileName,
+						pui32Registers,
+						ui32NumRegisters,
+						&ui32FileOffset,
+						sizeof(IMG_UINT32),
+						ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name		PDumpTASignatureRegisters
+ @brief		Dumps the TA signature registers
+ @param		psDevId - device id info
+ @param		ui32DumpFrameNum - frame number
+ @param		ui32TAKickCount - TA kick counter
+ @param		bLastFrame
+ @param		pui32Registers - register list
+ @param		ui32NumRegisters - number of regs to dump
+ @return	Error
+*****************************************************************************/
+PVRSRV_ERROR PDumpTASignatureRegisters	(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+			 IMG_UINT32 ui32DumpFrameNum,
+			 IMG_UINT32	ui32TAKickCount,
+			 IMG_BOOL	bLastFrame,
+			 IMG_UINT32 *pui32Registers,
+			 IMG_UINT32 ui32NumRegisters)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32FileOffset, ui32Flags;
+	PDUMP_GET_FILE_STRING();
+
+	ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+	ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(IMG_UINT32);
+
+	PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump TA signature registers\r\n");
+	eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_ta.sig", ui32DumpFrameNum);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+
+	/*
+		Note:
+		PDumpCommentWithFlags will take the lock so we defer the lock
+		taking until here
+	*/
+	PDUMP_LOCK();
+	PDumpRegisterRange(psDevId,
+						pszFileName, 
+						pui32Registers, 
+						ui32NumRegisters, 
+						&ui32FileOffset, 
+						sizeof(IMG_UINT32), 
+						ui32Flags);
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name		PDumpCounterRegisters
+ @brief		Dumps the performance counters
+ @param		psDevId - device id info
+ @param		ui32DumpFrameNum - frame number
+ @param		bLastFrame
+ @param		pui32Registers - register list
+ @param		ui32NumRegisters - number of regs to dump
+ @return	Error
+*****************************************************************************/
+PVRSRV_ERROR PDumpCounterRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+								IMG_UINT32 ui32DumpFrameNum,
+								IMG_BOOL	bLastFrame,
+								IMG_UINT32 *pui32Registers,
+								IMG_UINT32 ui32NumRegisters)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32	ui32FileOffset, ui32Flags;
+	PDUMP_GET_FILE_STRING();
+
+	ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0UL;
+	ui32FileOffset = 0UL;
+
+	PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump counter registers\r\n");
+	eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u.perf", ui32DumpFrameNum);
+	if(eErr != PVRSRV_OK)
+	{
+		return eErr;
+	}
+	/*
+		Note:
+		PDumpCommentWithFlags will take the lock so we defer the lock
+		taking until here
+	*/
+	PDUMP_LOCK();
+	PDumpRegisterRange(psDevId,
+						pszFileName,
+						pui32Registers,
+						ui32NumRegisters,
+						&ui32FileOffset,
+						sizeof(IMG_UINT32),
+						ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name		PDumpRegRead
+ @brief		Dump signature register read to script
+ @param		pszPDumpDevName - pdump device name
+ @param		ui32RegOffset - register offset
+ @param		ui32Flags - pdump flags
+ @return	Error
+*****************************************************************************/
+PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+							const IMG_UINT32 ui32RegOffset,
+							IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n",
+							pszPDumpRegName, 
+							ui32RegOffset);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name		PDumpSaveMemKM
+ @brief		Save device memory to a file
+ @param		psDevId
+ @param		pszFileName
+ @param		ui32FileOffset
+ @param		sDevBaseAddr
+ @param		ui32Size
+ @param		ui32PDumpFlags
+ @return	Error
+*****************************************************************************/
+PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+							 IMG_CHAR			*pszFileName,
+							 IMG_UINT32			ui32FileOffset,
+							 IMG_DEV_VIRTADDR	sDevBaseAddr,
+							 IMG_UINT32 		ui32Size,
+							 IMG_UINT32			ui32MMUContextID,
+							 IMG_UINT32 		ui32PDumpFlags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	eErr = PDumpOSBufprintf(hScript,
+							ui32MaxLen,
+							"SAB :%s:v%x:0x%08X 0x%08X 0x%08X %s.bin\r\n",
+							psDevId->pszPDumpDevName,
+							ui32MMUContextID,
+							sDevBaseAddr.uiAddr,
+							ui32Size,
+							ui32FileOffset,
+							pszFileName);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	PDumpOSWriteString2(hScript, ui32PDumpFlags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ @name		PDumpCycleCountRegRead
+ @brief		Dump counter register read to script
+ @param		ui32RegOffset - register offset
+ @param		bLastFrame
+ @return	Error
+*****************************************************************************/
+PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+									const IMG_UINT32 ui32RegOffset,
+									IMG_BOOL bLastFrame)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n", 
+							psDevId->pszPDumpRegName,
+							ui32RegOffset);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PDumpSignatureBuffer
+
+ @Description
+
+ Dumps a signature registers buffer
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PDumpSignatureBuffer (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+								   IMG_CHAR			*pszFileName,
+								   IMG_CHAR			*pszBufferType,
+								   IMG_UINT32		ui32FileOffset,
+								   IMG_DEV_VIRTADDR	sDevBaseAddr,
+								   IMG_UINT32 		ui32Size,
+								   IMG_UINT32		ui32MMUContextID,
+								   IMG_UINT32 		ui32PDumpFlags)
+{
+	PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump microkernel %s signature Buffer\r\n",
+						  pszBufferType);
+	PDumpCommentWithFlags(ui32PDumpFlags, "Buffer format (sizes in 32-bit words):\r\n");
+	PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of signatures per sample (1)\r\n");
+	PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of samples (1)\r\n");
+	PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature register offsets (1 * number of signatures)\r\n");
+	PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature sample values (number of samples * number of signatures)\r\n");
+	PDumpCommentWithFlags(ui32PDumpFlags, "Note: If buffer is full, last sample is final state after test completed\r\n");
+	return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+						  ui32MMUContextID, ui32PDumpFlags);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PDumpHWPerfCBKM
+
+ @Description
+
+ Dumps the HW Perf Circular Buffer
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PDumpHWPerfCBKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+							  IMG_CHAR			*pszFileName,
+							  IMG_UINT32		ui32FileOffset,
+							  IMG_DEV_VIRTADDR	sDevBaseAddr,
+							  IMG_UINT32 		ui32Size,
+							  IMG_UINT32		ui32MMUContextID,
+							  IMG_UINT32 		ui32PDumpFlags)
+{
+	PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+	return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+						  ui32MMUContextID, ui32PDumpFlags);
+}
+
+
+/*****************************************************************************
+ FUNCTION	: PDumpCBP
+
+ PURPOSE	: Dump CBP command to script
+
+ PARAMETERS	:
+
+ RETURNS	: None
+*****************************************************************************/
+PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO		psROffMemInfo,
+			  IMG_UINT32					ui32ROffOffset,
+			  IMG_UINT32					ui32WPosVal,
+			  IMG_UINT32					ui32PacketSize,
+			  IMG_UINT32					ui32BufferSize,
+			  IMG_UINT32					ui32Flags,
+			  IMG_HANDLE					hUniqueTag)
+{
+	PVRSRV_ERROR eErr;
+	IMG_UINT32			ui32PageOffset;
+	IMG_UINT8			*pui8LinAddr;
+	IMG_DEV_VIRTADDR	sDevVAddr;
+	IMG_DEV_PHYADDR		sDevPAddr;
+	IMG_DEV_VIRTADDR 	sDevVPageAddr;
+    //IMG_CPU_PHYADDR     CpuPAddr;
+	PDUMP_MMU_ATTRIB *psMMUAttrib;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	psMMUAttrib = ((BM_BUF*)psROffMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+	/* Check the offset and size don't exceed the bounds of the allocation */
+	PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->uAllocSize);
+
+	pui8LinAddr = psROffMemInfo->pvLinAddrKM;
+	sDevVAddr = psROffMemInfo->sDevVAddr;
+
+	/* Advance addresses by offset */
+	pui8LinAddr += ui32ROffOffset;
+	sDevVAddr.uiAddr += ui32ROffOffset;
+
+	/*
+		query the buffer manager for the physical pages that back the
+		virtual address
+	*/
+	PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
+			ui32ROffOffset,
+			pui8LinAddr,
+			psMMUAttrib->ui32DataPageMask,
+			&ui32PageOffset);
+
+	/* calculate the DevV page address */
+	sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+	PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+	/* get the physical page address based on the device virtual address */
+	BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+	/* convert DevP page address to byte address */
+	sDevPAddr.uiAddr += ui32PageOffset;
+
+	eErr = PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "CBP :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+			 psMMUAttrib->sDevId.pszPDumpDevName,
+			 (IMG_UINTPTR_T)hUniqueTag,
+			 sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+			 (unsigned int)(sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask)),
+			 ui32WPosVal,
+			 ui32PacketSize,
+			 ui32BufferSize);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name  : PDumpIDLWithFlags
+ * Inputs         : Idle time in clocks
+ * Outputs        : None
+ * Returns        : Error
+ * Description    : Dump IDL command to script
+**************************************************************************/
+PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	PDUMP_DBG(("PDumpIDLWithFlags"));
+
+	eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %u\r\n", ui32Clocks);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name  : PDumpIDL
+ * Inputs         : Idle time in clocks
+ * Outputs        : None
+ * Returns        : Error
+ * Description    : Dump IDL command to script
+**************************************************************************/
+PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+	return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+
+/**************************************************************************
+ * Function Name  : PDumpMemUM
+ * Inputs         : pvAltLinAddrUM
+ *				  : pvLinAddrUM
+ *				  : psMemInfo
+ *				  : ui32Offset
+ *				  : ui32Bytes
+ *				  : ui32Flags
+ *				  : hUniqueTag
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Dump user mode memory
+**************************************************************************/
+PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+						IMG_PVOID pvAltLinAddrUM,
+						IMG_PVOID pvLinAddrUM,
+						PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+						IMG_UINT32 ui32Offset,
+						IMG_UINT32 ui32Bytes,
+						IMG_UINT32 ui32Flags,
+						IMG_HANDLE hUniqueTag)
+{
+	IMG_VOID *pvAddrUM;
+	IMG_VOID *pvAddrKM;
+	PVRSRV_ERROR eError;
+
+	if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
+	{
+		/*
+		 * There is a kernel virtual address for the memory that is
+		 * being dumped, and no alternate user mode linear address.
+		 */
+		return PDumpMemKM(IMG_NULL,
+					   psMemInfo,
+					   ui32Offset,
+					   ui32Bytes,
+					   ui32Flags,
+					   hUniqueTag);
+	}
+
+	pvAddrUM = (pvAltLinAddrUM != IMG_NULL) ? pvAltLinAddrUM : ((pvLinAddrUM != IMG_NULL) ? VPTR_PLUS(pvLinAddrUM, ui32Offset) : IMG_NULL);
+
+	pvAddrKM = GetTempBuffer();
+
+	/*
+	 * The memory to be dumped needs to be copied in from
+	 * the client.  Dump the memory, a buffer at a time.
+	 */
+	PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
+	if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
+	{
+		PDumpCommentWithFlags(ui32Flags, "Dumping 0x%08x bytes of memory, in blocks of 0x%08x bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
+	}
+
+	if (psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE)
+	{
+		/*
+			In case of sparse mappings we can't just copy the full range as not
+			all pages are valid, instead we walk a page at a time only dumping
+			if the a page exists at that address
+		*/
+		IMG_UINT32 ui32BytesRemain = ui32Bytes;
+		IMG_UINT32 ui32BytesToCopy = 0;
+		IMG_UINT32 ui32InPageStart = ui32Offset & (~HOST_PAGEMASK);
+		IMG_UINT32 ui32PageOffset = ui32Offset & (HOST_PAGEMASK);
+		IMG_UINT32 ui32InPhyPageStart = 0;
+
+		if(ui32InPageStart != 0)
+		{
+			IMG_UINT32 ui32DummyInPageStart = 0;
+			
+			while(ui32DummyInPageStart != ui32InPageStart)
+			{
+				if (BM_MapPageAtOffset(BM_MappingHandleFromBuffer(psMemInfo->sMemBlk.hBuffer), ui32DummyInPageStart))
+				{
+					ui32InPhyPageStart += HOST_PAGESIZE();
+				}
+				ui32DummyInPageStart += HOST_PAGESIZE();
+			}
+		}
+
+		do
+		{
+			ui32BytesToCopy = MIN(HOST_PAGESIZE() - ui32PageOffset, ui32BytesRemain);
+
+			if (BM_MapPageAtOffset(BM_MappingHandleFromBuffer(psMemInfo->sMemBlk.hBuffer), ui32InPageStart))
+			{
+				eError = OSCopyFromUser(psPerProc,
+							   pvAddrKM,
+							   pvAddrUM,
+							   ui32BytesToCopy);
+				if (eError != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+					return eError;
+				}
+
+				/*
+					At this point we know we're dumping a valid page so call
+					the internal function
+				*/
+				eError = _PDumpMemIntKM(pvAddrKM,
+										psMemInfo,
+										ui32PageOffset + ui32InPageStart,
+										ui32PageOffset + ui32InPhyPageStart,
+										ui32BytesToCopy,
+										ui32Flags,
+										hUniqueTag);
+		
+				if (eError != PVRSRV_OK)
+				{
+					/*
+					 * If writing fails part way through, then some
+					 * investigation is needed.
+					 */
+					if (ui32BytesToCopy != 0)
+					{
+						PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+					}
+					PVR_ASSERT(ui32BytesToCopy == 0);
+					return eError;
+				}
+				ui32InPhyPageStart += HOST_PAGESIZE();
+			}
+
+			VPTR_INC(pvAddrUM, ui32BytesToCopy);
+			ui32BytesRemain -= ui32BytesToCopy;
+			ui32InPageStart += HOST_PAGESIZE();
+			ui32PageOffset = 0;
+
+		} while(ui32BytesRemain);
+	}
+	else
+	{
+		IMG_UINT32 ui32CurrentOffset = ui32Offset;
+		IMG_UINT32 ui32BytesDumped;
+
+		for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+		{
+			IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+	
+			eError = OSCopyFromUser(psPerProc,
+						   pvAddrKM,
+						   pvAddrUM,
+						   ui32BytesToDump);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+				return eError;
+			}
+	
+			eError = PDumpMemKM(pvAddrKM,
+						   psMemInfo,
+						   ui32CurrentOffset,
+						   ui32BytesToDump,
+						   ui32Flags,
+						   hUniqueTag);
+	
+			if (eError != PVRSRV_OK)
+			{
+				/*
+				 * If writing fails part way through, then some
+				 * investigation is needed.
+				 */
+				if (ui32BytesDumped != 0)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+				}
+				PVR_ASSERT(ui32BytesDumped == 0);
+				return eError;
+			}
+	
+			VPTR_INC(pvAddrUM, ui32BytesToDump);
+			ui32CurrentOffset += ui32BytesToDump;
+			ui32BytesDumped += ui32BytesToDump;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name  : _PdumpAllocMMUContext
+ * Inputs         : pui32MMUContextID
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : pdump util to allocate MMU contexts
+**************************************************************************/
+static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
+{
+	IMG_UINT32 i;
+
+	/* there are MAX_PDUMP_MMU_CONTEXTS contexts available, find one */
+	for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
+	{
+		if((gui16MMUContextUsage & (1U << i)) == 0)
+		{
+			/* mark in use */
+			gui16MMUContextUsage |= 1U << i;
+			*pui32MMUContextID = i;
+			return PVRSRV_OK;
+		}
+	}
+
+	PVR_DPF((PVR_DBG_ERROR, "_PdumpAllocMMUContext: no free MMU context ids"));
+
+	return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+/**************************************************************************
+ * Function Name  : _PdumpFreeMMUContext
+ * Inputs         : ui32MMUContextID
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : pdump util to free MMU contexts
+**************************************************************************/
+static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
+{
+	if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
+	{
+		/* free the id */
+		gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
+		return PVRSRV_OK;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR, "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+	return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+/**************************************************************************
+ * Function Name  : PDumpSetMMUContext
+ * Inputs         :
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Set MMU Context
+**************************************************************************/
+PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+								IMG_CHAR *pszMemSpace,
+								IMG_UINT32 *pui32MMUContextID,
+								IMG_UINT32 ui32MMUType,
+								IMG_HANDLE hUniqueTag1,
+								IMG_HANDLE hOSMemHandle, 
+								IMG_VOID *pvPDCPUAddr)
+{
+	IMG_UINT8 *pui8LinAddr = (IMG_UINT8 *)pvPDCPUAddr;
+	IMG_CPU_PHYADDR sCpuPAddr;
+	IMG_DEV_PHYADDR sDevPAddr;
+	IMG_UINT32 ui32MMUContextID;
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+
+	eErr = _PdumpAllocMMUContext(&ui32MMUContextID);
+	if(eErr != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eErr));
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	/* derive the DevPAddr */
+	/* FIXME: if we used OSMemHandleToCPUPAddr() here, we could lose the lin addr arg */
+	sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+	sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+	/* and round to 4k page */
+	sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
+
+	eErr = PDumpOSBufprintf(hScript,
+						ui32MaxLen, 
+						"MMU :%s:v%d %d :%s:PA_" UINTPTR_FMT DEVPADDR_FMT "\r\n",
+						pszMemSpace,
+						ui32MMUContextID,
+						ui32MMUType,
+						pszMemSpace,
+						(IMG_UINTPTR_T)hUniqueTag1,
+						sDevPAddr.uiAddr);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+	PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+	/* return the MMU Context ID */
+	*pui32MMUContextID = ui32MMUContextID;
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+
+/**************************************************************************
+ * Function Name  : PDumpClearMMUContext
+ * Inputs         :
+ * Outputs        : None
+ * Returns        : PVRSRV_ERROR
+ * Description    : Clear MMU Context
+**************************************************************************/
+PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+								IMG_CHAR *pszMemSpace,
+								IMG_UINT32 ui32MMUContextID,
+								IMG_UINT32 ui32MMUType)
+{
+	PVRSRV_ERROR eErr;
+	PDUMP_GET_SCRIPT_STRING();
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+	PVR_UNREFERENCED_PARAMETER(ui32MMUType);
+
+	/* FIXME: Propagate error from PDumpComment once it's supported on
+	 * all OSes and platforms
+	 */
+	PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
+
+	/*
+		Note:
+		PDumpComment takes the lock so we can't take it until here
+	*/
+	PDUMP_LOCK();
+	eErr = PDumpOSBufprintf(hScript,
+						ui32MaxLen, 
+						"MMU :%s:v%d\r\n",
+						pszMemSpace,
+						ui32MMUContextID);
+	if(eErr != PVRSRV_OK)
+	{
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+	eErr = _PdumpFreeMMUContext(ui32MMUContextID);
+	if(eErr != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eErr));
+		PDUMP_UNLOCK();
+		return eErr;
+	}
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;
+}
+
+/*****************************************************************************
+ FUNCTION	: PDumpStoreMemToFile
+    
+ PURPOSE	: Dumps a given addr:size to a file
+
+ PARAMETERS	:
+
+ RETURNS	: 
+*****************************************************************************/
+PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+						         IMG_CHAR *pszFileName,
+								 IMG_UINT32 ui32FileOffset, 
+								 PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								 IMG_UINT32 uiAddr, 
+								 IMG_UINT32 ui32Size,
+								 IMG_UINT32 ui32PDumpFlags,
+								 IMG_HANDLE hUniqueTag)
+{
+	IMG_DEV_PHYADDR		sDevPAddr;
+	IMG_DEV_VIRTADDR	sDevVPageAddr;
+	IMG_UINT32			ui32PageOffset;
+
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+	/*
+		query the buffer manager for the physical pages that back the
+		virtual address
+	*/
+	ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)psMemInfo->pvLinAddrKM & psMMUAttrib->ui32DataPageMask);
+	
+	/* calculate the DevV page address */
+	sDevVPageAddr.uiAddr = uiAddr - ui32PageOffset;
+	
+	/* get the physical page address based on the device virtual address */
+	BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+	
+	/* convert DevP page address to byte address */
+	sDevPAddr.uiAddr += ui32PageOffset;
+
+	PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "SAB :%s:PA_" UINTPTR_FMT DEVPADDR_FMT ":0x%08X 0x%08X 0x%08X %s\r\n",
+			 psMMUAttrib->sDevId.pszPDumpDevName,
+			 (IMG_UINTPTR_T)hUniqueTag,
+			 (sDevPAddr.uiAddr & ~psMMUAttrib->ui32DataPageMask),
+			 (unsigned int)(sDevPAddr.uiAddr & psMMUAttrib->ui32DataPageMask),
+			 ui32Size,
+			 ui32FileOffset,
+			 pszFileName);
+
+	PDumpOSWriteString2(hScript, ui32PDumpFlags);
+	
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;	
+}
+
+/*****************************************************************************
+ FUNCTION	: PDumpRegBasedCBP
+    
+ PURPOSE	: Dump CBP command to script
+
+ PARAMETERS	:
+			  
+ RETURNS	: None
+*****************************************************************************/
+PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR		*pszPDumpRegName,
+							  IMG_UINT32	ui32RegOffset,
+							  IMG_UINT32	ui32WPosVal,
+							  IMG_UINT32	ui32PacketSize,
+							  IMG_UINT32	ui32BufferSize,
+							  IMG_UINT32	ui32Flags)
+{
+	PDUMP_GET_SCRIPT_STRING();
+
+	PDUMP_LOCK();
+
+	PDumpOSBufprintf(hScript,
+			 ui32MaxLen,
+			 "CBP :%s:0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+			 pszPDumpRegName,
+			 ui32RegOffset,
+			 ui32WPosVal,
+			 ui32PacketSize,
+			 ui32BufferSize);
+	PDumpOSWriteString2(hScript, ui32Flags);
+
+	PDUMP_UNLOCK();
+	return PVRSRV_OK;		
+}
+
+
+/****************************************************
+ * Non-uitron code here.
+ * For example, code communicating with dbg driver.
+ ***************************************************/
+/* PRQA S 5087 1 */ /* include file needed here */
+#include "syscommon.h"
+
+/**************************************************************************
+ * Function Name  : PDumpConnectionNotify
+ * Description    : Called by the debugdrv to tell Services that pdump has
+ * 					connected
+ *					NOTE: No debugdrv on uitron.
+ **************************************************************************/
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID)
+{
+	SYS_DATA			*psSysData;
+	PVRSRV_DEVICE_NODE	*psThis;
+	PVR_DPF((PVR_DBG_WARNING, "PDump has connected."));
+	
+	/* Loop over all known devices */
+	SysAcquireData(&psSysData);
+	
+	psThis = psSysData->psDeviceNodeList;
+	while (psThis)
+	{
+		if (psThis->pfnPDumpInitDevice)
+		{
+			/* Reset pdump according to connected device */
+			psThis->pfnPDumpInitDevice(psThis);
+		}
+		psThis = psThis->psNext;
+	}
+}
+
+/*****************************************************************************
+ * Function Name  : DbgWrite
+ * Inputs         : psStream - debug stream to write to
+ 					pui8Data - buffer
+ 					ui32BCount - buffer length
+ 					ui32Flags - flags, e.g. continuous, LF
+ * Outputs        : None
+ * Returns        : Bytes written
+ * Description    : Write a block of data to a debug stream
+ *					NOTE: No debugdrv on uitron.
+ *****************************************************************************/
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+	IMG_UINT32	ui32BytesWritten = 0;
+	IMG_UINT32	ui32Off = 0;
+	PDBG_STREAM_CONTROL psCtrl = psStream->psCtrl;
+
+	/* Return immediately if marked as "never" */
+	if ((ui32Flags & PDUMP_FLAGS_NEVER) != 0)
+	{
+		return ui32BCount;
+	}
+	
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	/* Return if process is not marked for pdumping, unless it's persistent.
+	 */
+	if ( (_PDumpIsProcessActive() == IMG_FALSE ) &&
+		 ((ui32Flags & PDUMP_FLAGS_PERSISTENT) == 0) && psCtrl->bInitPhaseComplete)
+	{
+		return ui32BCount;
+	}
+#endif
+
+	/* Send persistent data first ...
+	 * If we're still initialising the params will be captured to the
+	 * init stream in the call to pfnDBGDrivWrite2 below.
+	 */
+	if ( ((ui32Flags & PDUMP_FLAGS_PERSISTENT) != 0) && (psCtrl->bInitPhaseComplete) )
+	{
+		while (ui32BCount > 0)
+		{
+			/*
+				Params marked as persistent should be appended to the init phase.
+				For example window system mem mapping of the primary surface.
+			*/
+			ui32BytesWritten = PDumpOSDebugDriverWrite(	psStream,
+														PDUMP_WRITE_MODE_PERSISTENT,
+														&pui8Data[ui32Off], ui32BCount, 1, 0);
+
+			if (ui32BytesWritten == 0)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "DbgWrite: Failed to send persistent data"));
+				PDumpOSReleaseExecution();
+			}
+
+			if (ui32BytesWritten != 0xFFFFFFFFU)
+			{
+				ui32Off += ui32BytesWritten;
+				ui32BCount -= ui32BytesWritten;
+			}
+			else
+			{
+				PVR_DPF((PVR_DBG_ERROR, "DbgWrite: Failed to send persistent data"));
+				if( (psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) != 0)
+				{
+					/* suspend pdump to prevent flooding kernel log buffer */
+					PDumpSuspendKM();
+				}
+				return 0xFFFFFFFFU;
+			}
+		}
+		
+		/* reset buffer counters */
+		ui32BCount = ui32Off; ui32Off = 0; ui32BytesWritten = 0;
+	}
+
+	while (((IMG_UINT32) ui32BCount > 0) && (ui32BytesWritten != 0xFFFFFFFFU))
+	{
+		/* If we're in the init phase we treat persisent as meaning continuous */
+		if (((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0) || ((ui32Flags & PDUMP_FLAGS_PERSISTENT) != 0))
+		{
+			/*
+				If pdump client (or its equivalent) isn't running then throw continuous data away.
+			*/
+			if (((psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+				 (psCtrl->ui32Start == 0xFFFFFFFFU) &&
+				 (psCtrl->ui32End == 0xFFFFFFFFU) &&
+				  psCtrl->bInitPhaseComplete)
+			{
+				ui32BytesWritten = ui32BCount;
+			}
+			else
+			{
+				ui32BytesWritten = PDumpOSDebugDriverWrite(	psStream, 
+															PDUMP_WRITE_MODE_CONTINUOUS,
+															&pui8Data[ui32Off], ui32BCount, 1, 0);
+			}
+		}
+		else
+		{
+			if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+			{
+				IMG_UINT32	ui32DbgFlags;
+	
+				ui32DbgFlags = 0;
+				if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+				{
+					ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+				}
+	
+				ui32BytesWritten = PDumpOSDebugDriverWrite(	psStream,
+															PDUMP_WRITE_MODE_LASTFRAME,
+															&pui8Data[ui32Off], ui32BCount, 1, ui32DbgFlags);
+			}
+			else
+			{
+				ui32BytesWritten = PDumpOSDebugDriverWrite(	psStream, 
+															PDUMP_WRITE_MODE_BINCM,
+															&pui8Data[ui32Off], ui32BCount, 1, 0);
+			}
+		}
+
+		/*
+			If the debug driver's buffers are full so no data could be written then yield
+			execution so pdump can run and empty them.
+		*/
+		if (ui32BytesWritten == 0)
+		{
+			if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Buffer is full during writing of %s", &pui8Data[ui32Off]));
+			}
+			PDumpOSReleaseExecution();
+		}
+
+		if (ui32BytesWritten != 0xFFFFFFFFU)
+		{
+			ui32Off += ui32BytesWritten;
+			ui32BCount -= ui32BytesWritten;
+		}
+		else
+		{
+			if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Error during writing of %s", &pui8Data[ui32Off]));
+			}
+		}
+		/* loop exits when i) all data is written, or ii) an unrecoverable error occurs */
+	}
+
+	return ui32BytesWritten;
+}
+
+
+
+#else	/* defined(PDUMP) */
+/* disable warning about empty module */
+#endif	/* defined(PDUMP) */
+/*****************************************************************************
+ End of file (pdump_common.c)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/perproc.c b/drivers/gpu/pvr/services4/srvkm/common/perproc.c
new file mode 100644
index 0000000..3918bb2
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/perproc.c
@@ -0,0 +1,398 @@
+/*************************************************************************/ /*!
+@Title          Per-process storage
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Manage per-process storage
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+#include "handle.h"
+#include "perproc.h"
+#include "osperproc.h"
+#if defined(TTRACE)
+#include "ttrace.h"
+#endif
+
+#define	HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = IMG_NULL;
+
+/*!
+******************************************************************************
+
+ @Function	FreePerProcData
+
+ @Description	Free a per-process data area
+
+ @Input		psPerProc - pointer to per-process data area
+
+ @Return	Error code, or PVRSRV_OK
+
+******************************************************************************/
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_UINTPTR_T uiPerProc;
+
+	PVR_ASSERT(psPerProc != IMG_NULL);
+
+	if (psPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID);
+	if (uiPerProc == 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
+		/*
+		 * We must have failed early in the per-process data area
+		 * creation, before the process ID was set.
+		 */
+		PVR_ASSERT(psPerProc->ui32PID == 0);
+	}
+	else
+	{
+		PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc);
+		PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
+	}
+
+	/* Free handle base for this process */
+	if (psPerProc->psHandleBase != IMG_NULL)
+	{
+		eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError));
+			return eError;
+		}
+	}
+
+	/* Release handle for per-process data area */
+	if (psPerProc->hPerProcData != IMG_NULL)
+	{
+		eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError));
+			return eError;
+		}
+	}
+
+	/* Call environment specific per process deinit function */
+	eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
+	if (eError != PVRSRV_OK)
+	{
+		 PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError));
+		return eError;
+	}
+
+	eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+		sizeof(*psPerProc),
+		psPerProc,
+		psPerProc->hBlockAlloc);
+	/*not nulling pointer, copy on stack*/
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPerProcessData
+ 
+ @Description	Return per-process data area
+
+ @Input		ui32PID - process ID
+ 
+ @Return	Pointer to per-process data area, or IMG_NULL on error.
+
+******************************************************************************/
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
+{
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+	PVR_ASSERT(psHashTab != IMG_NULL);
+
+	/* Look for existing per-process data area */
+	psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+	return psPerProc;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPerProcessDataConnect
+ 
+ @Description	Allocate per-process data area, or increment refcount if one
+ 				already exists for this PID.
+
+ @Input		ui32PID - process ID
+ 			ppsPerProc - Pointer to per-process data area
+ 
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32	ui32PID, IMG_UINT32 ui32Flags)
+{
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+	IMG_HANDLE hBlockAlloc;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (psHashTab == IMG_NULL)
+	{
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+
+	/* Look for existing per-process data area */
+	psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+
+	if (psPerProc == IMG_NULL)
+	{
+		/* Allocate per-process data area */
+		eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+							sizeof(*psPerProc),
+							(IMG_PVOID *)&psPerProc,
+							&hBlockAlloc,
+							"Per Process Data");
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError));
+			return eError;
+		}
+		OSMemSet(psPerProc, 0, sizeof(*psPerProc));
+		psPerProc->hBlockAlloc = hBlockAlloc;
+
+		if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
+			eError = PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED;
+			goto failure;
+		}
+
+		psPerProc->ui32PID = ui32PID;
+		psPerProc->ui32RefCount = 0;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+		if (ui32Flags == SRV_FLAGS_PDUMP_ACTIVE)
+		{
+			psPerProc->bPDumpActive = IMG_TRUE;
+		}
+#else
+		PVR_UNREFERENCED_PARAMETER(ui32Flags);
+#endif
+
+		/* Call environment specific per process init function */
+		eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
+		if (eError != PVRSRV_OK)
+		{
+			 PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError));
+			goto failure;
+		}
+
+		/* Allocate a handle for the per-process data area */
+		eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+								   &psPerProc->hPerProcData,
+								   psPerProc,
+								   PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+								   PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError));
+			goto failure;
+		}
+
+		/* Allocate handle base for this process */
+		eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError));
+			goto failure;
+		}
+
+		/* Set per-process handle options */
+		eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError));
+			goto failure;
+		}
+		
+		/* Create a resource manager context for the process */
+		eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
+			goto failure;
+		}
+#if defined (TTRACE)
+		PVRSRVTimeTraceBufferCreate(ui32PID);
+#endif
+	}
+	
+	psPerProc->ui32RefCount++;
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
+			ui32PID, psPerProc->ui32RefCount));
+
+	return eError;
+
+failure:
+	(IMG_VOID)FreePerProcessData(psPerProc);
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPerProcessDataDisconnect
+ 
+ @Description	Decrement refcount for per-process data area, 
+ 				and free the resources if necessary.
+
+ @Input		ui32PID - process ID
+ 
+ @Return	IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32	ui32PID)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+	PVR_ASSERT(psHashTab != IMG_NULL);
+
+	psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+	if (psPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID));
+	}
+	else
+	{
+		psPerProc->ui32RefCount--;
+		if (psPerProc->ui32RefCount == 0)
+		{
+			PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
+					"Last close from process 0x%x received", ui32PID));
+
+			/* Close the Resource Manager connection */
+			PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
+
+#if defined (TTRACE)
+			PVRSRVTimeTraceBufferDestroy(ui32PID);
+#endif
+
+			/* Free the per-process data */
+			eError = FreePerProcessData(psPerProc);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
+			}
+		}
+	}
+
+	eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError));
+	}
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPerProcessDataInit
+
+ @Description	Initialise per-process data management
+
+ @Return	Error code, or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
+{
+	PVR_ASSERT(psHashTab == IMG_NULL);
+
+	/* Create hash table */
+	psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
+	if (psHashTab == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
+		return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPerProcessDataDeInit
+
+ @Description	De-initialise per-process data management
+
+ @Return	Error code, or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
+{
+	/* Destroy per-process data area hash table */
+	if (psHashTab != IMG_NULL)
+	{
+		/* Free the hash table */
+		HASH_Delete(psHashTab);
+		psHashTab = IMG_NULL;
+	}
+
+	return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (perproc.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/power.c b/drivers/gpu/pvr/services4/srvkm/common/power.c
new file mode 100644
index 0000000..511a690
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/power.c
@@ -0,0 +1,996 @@
+/*************************************************************************/ /*!
+@Title          Power management functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Main APIs for power management functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "pdump_km.h"
+
+#include "lists.h"
+
+static IMG_BOOL gbInitServerRunning = IMG_FALSE;
+static IMG_BOOL gbInitServerRan = IMG_FALSE;
+static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSetInitServerState
+
+ @Description	Sets given services init state.
+
+ @Input		eInitServerState : a services init state
+ @Input		bState : a state to set
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
+{
+
+	switch(eInitServerState)
+	{
+		case PVRSRV_INIT_SERVER_RUNNING:
+			gbInitServerRunning	= bState;
+			break;
+		case PVRSRV_INIT_SERVER_RAN:
+			gbInitServerRan	= bState;
+			break;
+		case PVRSRV_INIT_SERVER_SUCCESSFUL:
+			gbInitSuccessful = bState;
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVSetInitServerState : Unknown state %x", eInitServerState));
+			return PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetInitServerState
+
+ @Description	Tests whether a given services init state was run.
+
+ @Input		eInitServerState : a services init state
+
+ @Return	IMG_BOOL
+
+******************************************************************************/
+IMG_EXPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+	IMG_BOOL	bReturnVal;
+
+	switch(eInitServerState)
+	{
+		case PVRSRV_INIT_SERVER_RUNNING:
+			bReturnVal = gbInitServerRunning;
+			break;
+		case PVRSRV_INIT_SERVER_RAN:
+			bReturnVal = gbInitServerRan;
+			break;
+		case PVRSRV_INIT_SERVER_SUCCESSFUL:
+			bReturnVal = gbInitSuccessful;
+			break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVGetInitServerState : Unknown state %x", eInitServerState));
+			bReturnVal = IMG_FALSE;
+	}
+
+	return bReturnVal;
+}
+
+/*!
+******************************************************************************
+
+ @Function	_IsSystemStatePowered
+
+ @Description	Tests whether a given system state represents powered-up.
+
+ @Input		eSystemPowerState : a system power state
+
+ @Return	IMG_BOOL
+
+******************************************************************************/
+static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+	return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPowerLock
+
+ @Description	Obtain the mutex for power transitions
+
+ @Input		ui32CallerID : KERNEL_ID or ISR_ID
+ @Input		bSystemPowerEvent : Only pass IMG_TRUE if the lock is for a
+ 								system power state change
+
+ @Return	PVRSRV_ERROR IMG_CALLCONV
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32	ui32CallerID,
+							 IMG_BOOL	bSystemPowerEvent)
+{
+	PVRSRV_ERROR	eError;
+	SYS_DATA	*psSysData;
+	IMG_UINT32	ui32Timeout = 1000000;
+	IMG_BOOL	bTryLock = (ui32CallerID == ISR_ID);
+
+	SysAcquireData(&psSysData);
+
+	eError = OSPowerLockWrap(bTryLock);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	do
+	{
+		eError = OSLockResource(&psSysData->sPowerStateChangeResource,
+								ui32CallerID);
+		if (eError == PVRSRV_OK)
+		{
+			break;
+		}
+		else if (bTryLock)
+		{
+			/*
+				ISR failed to acquire lock so it must be held by a kernel thread.
+			*/
+			eError = PVRSRV_ERROR_RETRY;
+			break;
+		}
+
+		OSWaitus(1);
+		ui32Timeout--;
+	} while (ui32Timeout > 0);
+
+	if (eError != PVRSRV_OK)
+	{
+		OSPowerLockUnwrap();
+	}
+
+	/* PRQA S 3415 3 */ /* side effects desired */
+	if ((eError == PVRSRV_OK) &&
+		!bSystemPowerEvent &&
+		!_IsSystemStatePowered(psSysData->eCurrentPowerState))
+	{
+		/* Reject device power state change due to system power state. */
+		PVRSRVPowerUnlock(ui32CallerID);
+		eError = PVRSRV_ERROR_RETRY;
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVPowerUnlock
+
+ @Description	Release the mutex for power transitions
+
+ @Input		ui32CallerID : KERNEL_ID or ISR_ID
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32	ui32CallerID)
+{
+	OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+	OSPowerLockUnwrap();
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDevicePrePowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input		psPowerDevice : the device
+ @Input		va : variable argument list with:
+ 				bAllDevices : IMG_TRUE - All devices
+ 						  	  IMG_FALSE - Use ui32DeviceIndex
+				ui32DeviceIndex : device index
+				eNewPowerState : New power state
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+	PVRSRV_ERROR			eError;
+
+	/*Variable Argument variables*/
+	IMG_BOOL				bAllDevices;
+	IMG_UINT32				ui32DeviceIndex;
+	PVRSRV_DEV_POWER_STATE	eNewPowerState;
+
+	/* WARNING: if types were not aligned to 4 bytes, this could be dangerous. */
+	bAllDevices = va_arg(va, IMG_BOOL);
+	ui32DeviceIndex = va_arg(va, IMG_UINT32);
+	eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+	{
+		eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+							psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+		if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+		{
+			if (psPowerDevice->pfnPrePower != IMG_NULL)
+			{
+				/* Call the device's power callback. */
+				eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
+													eNewDevicePowerState,
+													psPowerDevice->eCurrentPowerState);
+				if (eError != PVRSRV_OK)
+				{
+					return eError;
+				}
+			}
+
+			/* Do any required system-layer processing. */
+			eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
+											eNewDevicePowerState,
+											psPowerDevice->eCurrentPowerState);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+	}
+
+	return  PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDevicePrePowerStateKM
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input		bAllDevices : IMG_TRUE - All devices
+ 						  IMG_FALSE - Use ui32DeviceIndex
+ @Input		ui32DeviceIndex : device index
+ @Input		eNewPowerState : New power state
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL				bAllDevices,
+										 IMG_UINT32				ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE	eNewPowerState)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	/* Loop through the power devices. */
+	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+														&PVRSRVDevicePrePowerStateKM_AnyVaCb,
+														bAllDevices,
+														ui32DeviceIndex,
+														eNewPowerState);
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDevicePostPowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input		psPowerDevice : the device
+ @Input		va : variable argument list with:
+ 				bAllDevices : IMG_TRUE - All devices
+ 						  	  IMG_FALSE - Use ui32DeviceIndex
+				ui32DeviceIndex : device index
+				eNewPowerState : New power state
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+	PVRSRV_ERROR			eError;
+
+	/*Variable Argument variables*/
+	IMG_BOOL				bAllDevices;
+	IMG_UINT32				ui32DeviceIndex;
+	PVRSRV_DEV_POWER_STATE	eNewPowerState;
+
+	/* WARNING: if types were not aligned to 4 bytes, this could be dangerous. */
+	bAllDevices = va_arg(va, IMG_BOOL);
+	ui32DeviceIndex = va_arg(va, IMG_UINT32);
+	eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+	if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+	{
+		eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+								psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+		if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+		{
+			/* Do any required system-layer processing. */
+			eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
+											 eNewDevicePowerState,
+											 psPowerDevice->eCurrentPowerState);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+
+			if (psPowerDevice->pfnPostPower != IMG_NULL)
+			{
+				/* Call the device's power callback. */
+				eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
+													 eNewDevicePowerState,
+													 psPowerDevice->eCurrentPowerState);
+				if (eError != PVRSRV_OK)
+				{
+					return eError;
+				}
+			}
+
+			psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+		}
+	}
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDevicePostPowerStateKM
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input		bAllDevices : IMG_TRUE - All devices
+ 						  IMG_FALSE - Use ui32DeviceIndex
+ @Input		ui32DeviceIndex : device index
+ @Input		eNewPowerState : New power state
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL					bAllDevices,
+										  IMG_UINT32				ui32DeviceIndex,
+										  PVRSRV_DEV_POWER_STATE	eNewPowerState)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	/* Loop through the power devices. */
+	eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+														&PVRSRVDevicePostPowerStateKM_AnyVaCb,
+														bAllDevices,
+														ui32DeviceIndex,
+														eNewPowerState);
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSetDevicePowerStateKM
+
+ @Description	Set the Device into a new state
+
+ @Input		ui32DeviceIndex : device index
+ @Input		eNewPowerState : New power state
+ @Input		ui32CallerID : KERNEL_ID or ISR_ID
+ @Input		bRetainMutex : If true, the power mutex is retained on exit
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32				ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE	eNewPowerState)
+{
+	PVRSRV_ERROR	eError;
+	SYS_DATA		*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	#if defined(PDUMP)
+	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+	{
+		/*
+			Pdump a power-up regardless of the default state.
+			Then disable pdump and transition to the default power state.
+			This ensures that a power-up is always present in the pdump when necessary.
+		*/
+		eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+		if(eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+
+		eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+
+		PDUMPSUSPEND();
+	}
+	#endif /* PDUMP */
+
+	eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+	if(eError != PVRSRV_OK)
+	{
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+		{
+			PDUMPRESUME();
+		}
+		goto Exit;
+	}
+
+	eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+
+	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+	{
+		PDUMPRESUME();
+	}
+
+Exit:
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSystemPrePowerStateKM
+
+ @Description	Perform processing required before a system power transition
+
+ @Input		eNewSysPowerState :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+	PVRSRV_ERROR			eError;
+	SYS_DATA				*psSysData;
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+
+	SysAcquireData(&psSysData);
+
+	/* This mutex is unlocked in PVRSRVSystemPostPowerStateKM() */
+	eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	if (_IsSystemStatePowered(eNewSysPowerState) !=
+		_IsSystemStatePowered(psSysData->eCurrentPowerState))
+	{
+		if (_IsSystemStatePowered(eNewSysPowerState))
+		{
+			/* Return device back to its default state. */
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+		}
+		else
+		{
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+		}
+
+		/* Perform device-specific transitions. */
+		eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+	if (eNewSysPowerState != psSysData->eCurrentPowerState)
+	{
+		/* Perform system-specific power transitions. */
+		eError = SysSystemPrePowerState(eNewSysPowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+	return eError;
+
+ErrorExit:
+
+	PVR_DPF((PVR_DBG_ERROR,
+			"PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
+			psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+	/* save the power state for the re-attempt */
+	psSysData->eFailedPowerState = eNewSysPowerState;
+
+	PVRSRVPowerUnlock(KERNEL_ID);
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSystemPostPowerStateKM
+
+ @Description	Perform processing required after a system power transition
+
+ @Input		eNewSysPowerState :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+	PVRSRV_ERROR			eError = PVRSRV_OK;
+	SYS_DATA				*psSysData;
+	PVRSRV_DEV_POWER_STATE	eNewDevicePowerState;
+
+	SysAcquireData(&psSysData);
+
+	if (eNewSysPowerState != psSysData->eCurrentPowerState)
+	{
+		/* Perform system-specific power transitions. */
+		eError = SysSystemPostPowerState(eNewSysPowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+	}
+
+	if (_IsSystemStatePowered(eNewSysPowerState) !=
+		_IsSystemStatePowered(psSysData->eCurrentPowerState))
+	{
+		if (_IsSystemStatePowered(eNewSysPowerState))
+		{
+			/* Return device back to its default state. */
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+		}
+		else
+		{
+			eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+		}
+
+		/* Perform device-specific power transitions. */
+		eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+			psSysData->eCurrentPowerState, eNewSysPowerState));
+
+	psSysData->eCurrentPowerState = eNewSysPowerState;
+
+Exit:
+
+	PVRSRVPowerUnlock(KERNEL_ID);
+
+	/* PRQA S 3415 2 */ /* side effects desired */
+	if (_IsSystemStatePowered(eNewSysPowerState) &&
+			PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+	{
+		/*
+			Reprocess the devices' queues in case commands were blocked during
+			the power transition.
+		*/
+		PVRSRVScheduleDeviceCallbacks();
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSetPowerStateKM
+
+ @Description	Set the system into a new state
+
+ @Input		eNewPowerState :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+	PVRSRV_ERROR	eError;
+	SYS_DATA		*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	eError = PVRSRVSystemPrePowerStateKM(eNewSysPowerState);
+	if(eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	eError = PVRSRVSystemPostPowerStateKM(eNewSysPowerState);
+	if(eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	/* save new power state */
+	psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	PVR_DPF((PVR_DBG_ERROR,
+			"PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+			psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+	/* save the power state for the re-attempt */
+	psSysData->eFailedPowerState = eNewSysPowerState;
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRegisterPowerDevice
+
+ @Description
+
+ Registers a device with the power manager.  Passes Pre/Post Power handlers
+ and private device handle to be passed to power handlers
+
+ @Input		ui32DeviceIndex : device index
+ @Input		pfnPrePower : Pre power transition handler
+ @Input		pfnPostPower : Post power transition handler
+ @Input		pfnPreClockSpeedChange : Pre clock speed transition handler (if required)
+ @Input		pfnPostClockSpeedChange : Post clock speed transition handler (if required)
+ @Input		hDevCookie : Dev cookie for dev power handlers
+ @Input		eCurrentPowerState : Current power state of the device
+ @Input		eDefaultPowerState : Default power state of the device
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32					ui32DeviceIndex,
+									   PFN_PRE_POWER				pfnPrePower,
+									   PFN_POST_POWER				pfnPostPower,
+									   PFN_PRE_CLOCKSPEED_CHANGE	pfnPreClockSpeedChange,
+									   PFN_POST_CLOCKSPEED_CHANGE	pfnPostClockSpeedChange,
+									   IMG_HANDLE					hDevCookie,
+									   PVRSRV_DEV_POWER_STATE		eCurrentPowerState,
+									   PVRSRV_DEV_POWER_STATE		eDefaultPowerState)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	if (pfnPrePower == IMG_NULL &&
+		pfnPostPower == IMG_NULL)
+	{
+		return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+	}
+
+	SysAcquireData(&psSysData);
+
+	eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+						 sizeof(PVRSRV_POWER_DEV),
+						 (IMG_VOID **)&psPowerDevice, IMG_NULL,
+						 "Power Device");
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+		return eError;
+	}
+
+	/* setup device for power manager */
+	psPowerDevice->pfnPrePower = pfnPrePower;
+	psPowerDevice->pfnPostPower = pfnPostPower;
+	psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+	psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+	psPowerDevice->hDevCookie = hDevCookie;
+	psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+	psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+	psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+	/* insert into power device list */
+	List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
+
+	return (PVRSRV_OK);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRemovePowerDevice
+
+ @Description
+
+ Removes device from power management register. Device is located by Device Index
+
+ @Input		ui32DeviceIndex : device index
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+{
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDev;
+
+	SysAcquireData(&psSysData);
+
+	/* find device in list and remove it */
+	psPowerDev = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 &MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+
+	if (psPowerDev)
+	{
+		List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+	}
+
+	return (PVRSRV_OK);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVIsDevicePowered
+
+ @Description
+
+	Whether the device is powered, for the purposes of lockup detection.
+
+ @Input		ui32DeviceIndex : device index
+
+ @Return	IMG_BOOL
+
+******************************************************************************/
+IMG_EXPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	SysAcquireData(&psSysData);
+
+	/* PRQA S 3415 2 */ /* order not important */
+	if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
+		OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
+	{
+		return IMG_FALSE;
+	}
+
+	psPowerDevice = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 &MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+	return (psPowerDevice && (psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON))
+			? IMG_TRUE : IMG_FALSE;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDevicePreClockSpeedChange
+
+ @Description
+
+	Notification from system layer that a device clock speed change is about to happen.
+
+ @Input		ui32DeviceIndex : device index
+ @Input		bIdleDevice : whether the device should be idled
+ @Input		pvInfo
+
+ @Return	IMG_VOID
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+											 IMG_BOOL	bIdleDevice,
+											 IMG_VOID	*pvInfo)
+{
+	PVRSRV_ERROR		eError = PVRSRV_OK;
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+	SysAcquireData(&psSysData);
+
+	if (bIdleDevice)
+	{
+		/* This mutex is released in PVRSRVDevicePostClockSpeedChange. */
+		eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,	"PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError));
+			return eError;
+		}
+	}
+
+	/*search the device and then do the pre clock speed change*/
+	psPowerDevice = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 &MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+
+	if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+	{
+			eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+														   bIdleDevice,
+														   psPowerDevice->eCurrentPowerState);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,
+						"PVRSRVDevicePreClockSpeedChange : Device %u failed, error:0x%x",
+						ui32DeviceIndex, eError));
+			}
+	}
+
+	if (bIdleDevice && eError != PVRSRV_OK)
+	{
+		PVRSRVPowerUnlock(KERNEL_ID);
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDevicePostClockSpeedChange
+
+ @Description
+
+	Notification from system layer that a device clock speed change has just happened.
+
+ @Input		ui32DeviceIndex : device index
+ @Input		bIdleDevice : whether the device had been idled
+ @Input		pvInfo
+
+ @Return	IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+										  IMG_BOOL		bIdleDevice,
+										  IMG_VOID		*pvInfo)
+{
+	PVRSRV_ERROR		eError;
+	SYS_DATA			*psSysData;
+	PVRSRV_POWER_DEV	*psPowerDevice;
+
+	PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+	SysAcquireData(&psSysData);
+
+	/*search the device and then do the post clock speed change*/
+	psPowerDevice = (PVRSRV_POWER_DEV*)
+					List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+												 &MatchPowerDeviceIndex_AnyVaCb,
+												 ui32DeviceIndex);
+
+	if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+	{
+		eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
+														bIdleDevice,
+														psPowerDevice->eCurrentPowerState);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+					"PVRSRVDevicePostClockSpeedChange : Device %u failed, error:0x%x",
+					ui32DeviceIndex, eError));
+		}
+	}
+
+
+	if (bIdleDevice)
+	{
+		/* This mutex was acquired in PVRSRVDevicePreClockSpeedChange. */
+		PVRSRVPowerUnlock(KERNEL_ID);
+	}
+}
+
+/******************************************************************************
+ End of file (power.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/pvrsrv.c b/drivers/gpu/pvr/services4/srvkm/common/pvrsrv.c
new file mode 100644
index 0000000..e823db4
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/pvrsrv.c
@@ -0,0 +1,1909 @@
+/*************************************************************************/ /*!
+@Title          core services functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Main APIs for core services functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pvr_bridge_km.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+#include "ra.h"
+#if defined(TTRACE)
+#include "ttrace.h"
+#endif
+#include "perfkm.h"
+#include "devicemem.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+
+IMG_UINT32	g_ui32InitFlags;
+
+/* mark which parts of Services were initialised */
+#define		INIT_DATA_ENABLE_PDUMPINIT	0x1U
+#define		INIT_DATA_ENABLE_TTRACE		0x2U
+#define		INIT_DATA_ENABLE_DEVMEM		0x4U
+
+/*!
+******************************************************************************
+
+ @Function	AllocateDeviceID
+
+ @Description
+
+ allocates a device id from the pool of valid ids
+
+ @input psSysData :	system data
+
+ @input pui32DevID : device id to return
+
+ @Return device id
+
+******************************************************************************/
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
+{
+	SYS_DEVICE_ID* psDeviceWalker;
+	SYS_DEVICE_ID* psDeviceEnd;
+
+	psDeviceWalker = &psSysData->sDeviceID[0];
+	psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+	/* find a free ID */
+	while (psDeviceWalker < psDeviceEnd)
+	{
+		if (!psDeviceWalker->bInUse)
+		{
+			psDeviceWalker->bInUse = IMG_TRUE;
+			*pui32DevID = psDeviceWalker->uiID;
+			return PVRSRV_OK;
+		}
+		psDeviceWalker++;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
+
+	/* Should never get here: sDeviceID[] may have been setup too small */
+	PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+	return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	FreeDeviceID
+
+ @Description
+
+ frees a device id from the pool of valid ids
+
+ @input psSysData :	system data
+
+ @input ui32DevID : device id to free
+
+ @Return device id
+
+******************************************************************************/
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
+{
+	SYS_DEVICE_ID* psDeviceWalker;
+	SYS_DEVICE_ID* psDeviceEnd;
+
+	psDeviceWalker = &psSysData->sDeviceID[0];
+	psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+	/* find the ID to free */
+	while (psDeviceWalker < psDeviceEnd)
+	{
+		/* if matching id and in use, free */
+		if	(
+				(psDeviceWalker->uiID == ui32DevID) &&
+				(psDeviceWalker->bInUse)
+			)
+		{
+			psDeviceWalker->bInUse = IMG_FALSE;
+			return PVRSRV_OK;
+		}
+		psDeviceWalker++;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
+
+	/* should never get here */
+	PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+	return PVRSRV_ERROR_INVALID_DEVICEID;
+}
+/*!
+******************************************************************************
+
+ @Function		PVRSRVCompatCheckKM
+
+ @Description   	UM/KM ddk branch Compatibility check function
+
+ @input 		psUserModeDDKDetails: User mode DDK version
+
+ @output		In case of incompatibility, returns PVRSRV_ERROR_DDK_VERSION_MISMATCH
+
+ @Return   		PVRSRV_ERROR
+
+******************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVCompatCheckKM(PVRSRV_BRIDGE_IN_COMPAT_CHECK *psUserModeDDKDetails, PVRSRV_BRIDGE_RETURN *psRetOUT)
+{
+#if defined(SUPPORT_TI_VERSION_STRING)
+	SYS_DATA			*psSysData;
+
+	SysAcquireData(&psSysData);
+#endif
+
+	if(psUserModeDDKDetails->ui32DDKVersion != ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8))
+		|| (psUserModeDDKDetails->ui32DDKBuild != PVRVERSION_BUILD))
+	{
+		psRetOUT->eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+		PVR_LOG(("(FAIL) UM-KM DDK Mismatch UM-(%d) KM-(%d).",
+						psUserModeDDKDetails->ui32DDKBuild, PVRVERSION_BUILD));
+	}
+	else
+	{
+		psRetOUT->eError = PVRSRV_OK;
+		PVR_LOG(("UM DDK-(%d) and KM DDK-(%d) match. [ OK ]",
+						psUserModeDDKDetails->ui32DDKBuild ,PVRVERSION_BUILD));
+	}
+
+#if defined(SUPPORT_TI_VERSION_STRING)
+	/* If TI version string is supported, populate it here. This will show
+	 * up in proc entry.
+	 * Probably a bad place to do this. FIXME
+	 */
+	memcpy(psSysData->szTIVersion, psUserModeDDKDetails->szTIVersion, 64);
+#endif
+}
+
+/*!
+******************************************************************************
+
+ @Function	ReadHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr :	lin addr of register block base
+
+ @input ui32Offset :	 byte offset from register base
+
+ @Return   register value
+
+******************************************************************************/
+#ifndef ReadHWReg
+IMG_EXPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+	return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
+}
+#endif
+
+
+/*!
+******************************************************************************
+
+ @Function	WriteHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr :	lin addr of register block base
+
+ @input ui32Offset :	 byte offset from register base
+
+ @input ui32Value :	 value to write to register
+
+ @Return   register value : original reg. value
+
+******************************************************************************/
+#ifndef WriteHWReg
+IMG_EXPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+	PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%p, Offset: %x, Value %x",
+			pvLinRegBaseAddr,ui32Offset,ui32Value));
+
+	*(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+}
+#endif
+
+
+/*!
+******************************************************************************
+
+ @Function	WriteHWRegs
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr :	lin addr of register block base
+
+ @input ui32Count :	 register count
+
+ @input psHWRegs :	 address/value register list
+
+ @Return   none
+
+******************************************************************************/
+#ifndef WriteHWRegs
+IMG_EXPORT
+IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
+{
+	while (ui32Count)
+	{
+		WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
+		psHWRegs++;
+		ui32Count--;
+	}
+}
+#endif
+
+/*!
+******************************************************************************
+ @Function	PVRSRVEnumerateDCKM_ForEachVaCb
+
+ @Description
+
+ Enumerates the device node (if is of the same class as given).
+
+ @Input psDeviceNode	- The device node to be enumerated
+ 		va				- variable arguments list, with:
+							pui32DevCount	- The device count pointer (to be increased)
+							ppui32DevID		- The pointer to the device IDs pointer (to be updated and increased)
+******************************************************************************/
+static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	IMG_UINT *pui32DevCount;
+	PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
+
+	pui32DevCount = va_arg(va, IMG_UINT*);
+	ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
+
+	if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
+	{
+		*(*ppsDevIdList) = psDeviceNode->sDevId;
+		(*ppsDevIdList)++;
+		(*pui32DevCount)++;
+	}
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumerateDevicesKM
+
+ @Description
+ This function will enumerate all the devices supported by the
+ PowerVR services within the target system.
+ The function returns a list of the device ID strcutres stored either in
+ the services or constructed in the user mode glue component in certain
+ environments. The number of devices in the list is also returned.
+
+ In a binary layered component which does not support dynamic runtime selection,
+ the glue code should compile to return the supported devices statically,
+ e.g. multiple instances of the same device if multiple devices are supported,
+ or the target combination of MBX and display device.
+
+ In the case of an environment (for instance) where one MBX1 may connect to two
+ display devices this code would enumerate all three devices and even
+ non-dynamic MBX1 selection code should retain the facility to parse the list
+ to find the index of the MBX device
+
+ @output pui32NumDevices :	On success, contains the number of devices present
+ 							in the system
+
+ @output psDevIdList	 :	Pointer to called supplied buffer to receive the
+ 							list of PVRSRV_DEVICE_IDENTIFIER
+
+ @return PVRSRV_ERROR  :	PVRSRV_NO_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+											 	   PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
+{
+	SYS_DATA			*psSysData;
+/*	PVRSRV_DEVICE_NODE	*psDeviceNode; */
+	IMG_UINT32 			i;
+
+	if (!pui32NumDevices || !psDevIdList)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	SysAcquireData(&psSysData);
+
+	/*
+		setup input buffer to be `empty'
+	*/
+	for (i=0; i<PVRSRV_MAX_DEVICES; i++)
+	{
+		psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+	}
+
+	/* and zero device count */
+	*pui32NumDevices = 0;
+
+	/*
+		Search through the device list for services managed devices
+		return id info for each device and the number of devices
+		available
+	*/
+	List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+									   &PVRSRVEnumerateDevicesKM_ForEachVaCb,
+									   pui32NumDevices,
+									   &psDevIdList);
+
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVInit
+
+ @Description	Initialise services
+
+ @Input	   psSysData	: sysdata structure
+
+ @Return   PVRSRV_ERROR	:
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
+{
+	PVRSRV_ERROR	eError;
+
+	/* Initialise Resource Manager */
+	eError = ResManInit();
+	if (eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+	eError = PVRSRVPerProcessDataInit();
+	if(eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+	/* Initialise handles */
+	eError = PVRSRVHandleInit();
+	if(eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+	/* Initialise Power Manager Lock */
+	eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
+	if (eError != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+	/* Initialise system power state */
+	psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+	psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+	/* Create an event object */
+	if((eError = OSAllocMem( PVRSRV_PAGEABLE_SELECT,
+					 sizeof(PVRSRV_EVENTOBJECT) ,
+					 (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
+					 "Event Object")) != PVRSRV_OK)
+	{
+
+		goto Error;
+	}
+
+	if((eError = OSEventObjectCreateKM("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject)) != PVRSRV_OK)
+	{
+		goto Error;
+	}
+
+	/* Store OS high res timer fallbacks, the system is free to overide these */
+	psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate;
+	psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus;
+	psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy;
+
+#if defined(TTRACE)
+	eError = PVRSRVTimeTraceInit();
+	if (eError != PVRSRV_OK)
+		goto Error;
+	g_ui32InitFlags |= INIT_DATA_ENABLE_TTRACE;
+#endif
+
+#if defined(PDUMP)
+	/* Initialise pdump */
+	PDUMPINIT();
+	g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
+#endif
+
+#if defined(SUPPORT_ION) || defined(SUPPORT_DMABUF)
+	eError = PVRSRVInitDeviceMem();
+	if (eError != PVRSRV_OK)
+		goto Error;
+	g_ui32InitFlags |= INIT_DATA_ENABLE_DEVMEM;
+#endif
+
+	PERFINIT();
+	return eError;
+
+Error:
+	PVRSRVDeInit(psSysData);
+	return eError;
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDeInit
+
+ @Description	De-Initialise services
+
+ @Input	   psSysData	: sysdata structure
+
+ @Return   PVRSRV_ERROR	:
+
+******************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
+{
+	PVRSRV_ERROR	eError;
+
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+
+	if (psSysData == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
+		return;
+	}
+
+	PERFDEINIT();
+
+
+#if defined(SUPPORT_ION) || defined(SUPPORT_DMABUF)
+	if ((g_ui32InitFlags & INIT_DATA_ENABLE_DEVMEM) > 0)
+	{
+		PVRSRVDeInitDeviceMem();
+	}
+#endif
+
+#if defined(MEM_TRACK_INFO_DEBUG)
+	/* Free the list of memory operations */
+	PVRSRVFreeMemOps();
+#endif
+
+#if defined(TTRACE)
+	/* deinitialise ttrace */
+	if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTRACE) > 0)
+	{
+		PVRSRVTimeTraceDeinit();
+	}
+#endif
+
+#if defined(PDUMP)
+	/* deinitialise pdump */
+	if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
+	{
+		PDUMPDEINIT();
+	}
+#endif
+
+	/* destroy event object */
+	if(psSysData->psGlobalEventObject)
+	{
+		OSEventObjectDestroyKM(psSysData->psGlobalEventObject);
+		OSFreeMem( PVRSRV_PAGEABLE_SELECT,
+						 sizeof(PVRSRV_EVENTOBJECT),
+						 psSysData->psGlobalEventObject,
+						 0);
+		psSysData->psGlobalEventObject = IMG_NULL;
+	}
+
+	eError = PVRSRVHandleDeInit();
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+	}
+
+	eError = PVRSRVPerProcessDataDeInit();
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
+	}
+
+	ResManDeInit();
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRegisterDevice
+
+ @Description
+
+ registers a device with the system
+
+ @Input	   psSysData			: sysdata structure
+
+ @Input	   pfnRegisterDevice	: device registration function
+
+ @Input	   ui32SOCInterruptBit	: SoC interrupt bit for this device
+
+ @Output	pui32DeviceIndex		: unique device key (for case of multiple identical devices)
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+											  PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+											  IMG_UINT32 ui32SOCInterruptBit,
+			 								  IMG_UINT32 *pui32DeviceIndex)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+
+	/* Allocate device node */
+	if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_DEVICE_NODE),
+					 (IMG_VOID **)&psDeviceNode, IMG_NULL,
+					 "Device Node") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+	eError = pfnRegisterDevice(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
+		return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
+	}
+
+	/*
+		make the refcount 1 and test on this to initialise device
+		at acquiredevinfo. On release if refcount is 1, deinitialise
+		and when refcount is 0 (sysdata de-alloc) deallocate the device
+		structures
+	*/
+	psDeviceNode->ui32RefCount = 1;
+	psDeviceNode->psSysData = psSysData;
+	psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
+
+	/* all devices need a unique identifier */
+	AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+	/* and finally insert the device into the dev-list */
+	List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+	/* and copy back index */
+	*pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVInitialiseDevice
+
+ @Description
+
+ initialises device by index
+
+ @Input	   ui32DevIndex : Index to the required device
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
+
+	SysAcquireData(&psSysData);
+
+	/* Find device in the list */
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+					 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+													&MatchDeviceKM_AnyVaCb,
+													ui32DevIndex,
+													IMG_TRUE);
+	if(!psDeviceNode)
+	{
+		/* Devinfo not in the list */
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+/*
+FoundDevice:
+*/
+
+	PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+	/*
+		Create the device's resource manager context.
+	*/
+	eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
+		return eError;
+	}
+
+	/* Initialise the device */
+	if(psDeviceNode->pfnInitDevice != IMG_NULL)
+	{
+		eError = psDeviceNode->pfnInitDevice(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
+			return eError;
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR eError;
+
+	eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVPowerLock call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+		return eError;
+	}
+
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE_DEFAULT);
+	PVRSRVPowerUnlock(KERNEL_ID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+	}
+	return eError;
+}
+
+/*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
+static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR eError;
+	eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+	}
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVFinaliseSystem
+
+ @Description
+
+ Final part of system initialisation.
+
+ @Input	   ui32DevIndex : Index to the required device
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+/*	PVRSRV_DEVICE_NODE	*psDeviceNode;*/
+	SYS_DATA		*psSysData;
+	PVRSRV_ERROR		eError;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+	SysAcquireData(&psSysData);
+
+	if (bInitSuccessful)
+	{
+		eError = SysFinalise();
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
+			return eError;
+		}
+
+		/* Place all devices into their default power state. */
+		eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+														&PVRSRVFinaliseSystem_SetPowerState_AnyCb);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+
+		/* Verify microkernel compatibility for devices */
+		eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+													&PVRSRVFinaliseSystem_CompatCheck_AnyCb);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	/* Some platforms call this too early in the boot phase. */
+	PDUMPENDINITPHASE();
+
+	return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	/* Only check devices which specify a compatibility check callback */
+	if (psDeviceNode->pfnInitDeviceCompatCheck)
+		return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+	else
+		return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Matchs a device given a device type and a device index.
+
+ @input	psDeviceNode :The device node to be matched.
+
+ @Input	   va : Variable argument list with:
+			eDeviceType : Required device type. If type is unknown use ui32DevIndex
+						 to locate device data
+
+ 			ui32DevIndex : Index to the required device obtained from the
+						PVRSRVEnumerateDevice function
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	PVRSRV_DEVICE_TYPE eDeviceType;
+	IMG_UINT32 ui32DevIndex;
+
+	eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+	ui32DevIndex = va_arg(va, IMG_UINT32);
+
+	if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+		psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+		(eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+		 psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
+	{
+		return psDeviceNode;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Returns device information
+
+ @Input	   ui32DevIndex : Index to the required device obtained from the
+						PVRSRVEnumerateDevice function
+
+ @Input	   eDeviceType : Required device type. If type is unknown use ui32DevIndex
+						 to locate device data
+
+ @Output  *phDevCookie : Dev Cookie
+
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32			ui32DevIndex,
+													 PVRSRV_DEVICE_TYPE	eDeviceType,
+													 IMG_HANDLE			*phDevCookie)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+
+	PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+	SysAcquireData(&psSysData);
+
+	/* Find device in the list */
+	psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+												&PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+												eDeviceType,
+												ui32DevIndex);
+
+
+	if (!psDeviceNode)
+	{
+		/* device can't be found in the list so it isn't in the system */
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+
+/*FoundDevice:*/
+
+	PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+	/* return the dev cookie? */
+	if (phDevCookie)
+	{
+		*phDevCookie = (IMG_HANDLE)psDeviceNode;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDeinitialiseDevice
+
+ @Description
+
+ This De-inits device
+
+ @Input	   ui32DevIndex : Index to the required device
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+
+	SysAcquireData(&psSysData);
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)
+					 List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+													&MatchDeviceKM_AnyVaCb,
+													ui32DevIndex,
+													IMG_TRUE);
+
+	if (!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
+		return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
+	}
+
+	eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVPowerLock call"));
+		return eError;
+	}
+
+	/*
+		Power down the device if necessary.
+	 */
+	eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+										 PVRSRV_DEV_POWER_STATE_OFF);
+	PVRSRVPowerUnlock(KERNEL_ID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
+		return eError;
+	}
+
+	/*
+		Free the dissociated device memory.
+	*/
+	eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
+									 RESMAN_CRITERIA_RESTYPE,
+									 RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+									 IMG_NULL, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
+		return eError;
+	}
+
+	/*
+		De-init the device.
+	*/
+	if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
+	{
+		eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
+			return eError;
+		}
+	}
+
+	/*
+		Close the device's resource manager context.
+	*/
+	PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
+	psDeviceNode->hResManContext = IMG_NULL;
+
+	/* remove node from list */
+	List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+	/* deallocate id and memory */
+	(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+	OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+
+	return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32*	pui32LinMemAddr,
+										  IMG_UINT32			ui32Value,
+										  IMG_UINT32			ui32Mask,
+										  IMG_UINT32			ui32Timeoutus,
+										  IMG_UINT32			ui32PollPeriodus,
+										  IMG_BOOL				bAllowPreemption)
+{
+#if defined (EMULATOR)
+	{
+		PVR_UNREFERENCED_PARAMETER(bAllowPreemption);
+		#if !defined(__linux__)
+		PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
+		#endif	
+		
+		/* For the Emulator we want the system to stop when a lock-up is detected so the state can be analysed.
+		 * Also the Emulator is much slower than real silicon so timeouts are not valid. 
+		 */
+		if((*pui32LinMemAddr & ui32Mask) == ui32Value)
+		{
+			return PVRSRV_OK;
+		}
+
+		do
+		{
+			#if defined(__linux__)
+			OSWaitus(ui32PollPeriodus);
+			#else
+			OSReleaseThreadQuanta();
+			#endif	
+
+			if((*pui32LinMemAddr & ui32Mask) == ui32Value)
+			{
+				return PVRSRV_OK;
+			}
+
+		} while (ui32Timeoutus); /* Endless loop only for the Emulator */
+	}
+#else
+	{
+		IMG_UINT32	ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */
+
+		if (bAllowPreemption)
+		{
+			PVR_ASSERT(ui32PollPeriodus >= 1000);
+		}
+
+		ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+		if(ui32ActualValue == ui32Value)
+		{
+			return PVRSRV_OK;
+		}
+
+		/* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
+		LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
+		{
+			if (bAllowPreemption)
+			{
+				OSSleepms(ui32PollPeriodus / 1000);
+			}
+			else
+			{
+				OSWaitus(ui32PollPeriodus);
+			}
+
+			ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+			if(ui32ActualValue == ui32Value)
+			{
+				return PVRSRV_OK;
+			}
+
+		} END_LOOP_UNTIL_TIMEOUT();
+	
+		PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
+				ui32Value, ui32ActualValue, ui32Mask));
+	}
+#endif /* #if defined (EMULATOR) */
+
+	return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+/*Level 3 of the loop nesting*/
+static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+	IMG_CHAR **ppszStr;
+	IMG_UINT32 *pui32StrLen;
+	IMG_UINT32 ui32Mode;
+	PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *);
+
+	ppszStr = va_arg(va, IMG_CHAR**);
+	pui32StrLen = va_arg(va, IMG_UINT32*);
+	ui32Mode = va_arg(va, IMG_UINT32);
+
+	/* Would be better to pass fn pointer in the variable args list
+	 * but MS C compiler complains with error C2066: In ANSI C,
+	 * it is not legal to cast between a function pointer and a data pointer.
+	 */
+	switch(ui32Mode)
+	{
+		case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
+			pfnGetStats = &RA_GetStats;
+			break;
+		case PVRSRV_MISC_INFO_FREEMEM_PRESENT:
+			pfnGetStats = &RA_GetStatsFreeMem;
+			break;
+		default:
+			return;
+	}
+
+	if(psBMHeap->pImportArena)
+	{
+		pfnGetStats(psBMHeap->pImportArena,
+					ppszStr,
+					pui32StrLen);
+	}
+
+	if(psBMHeap->pVMArena)
+	{
+		pfnGetStats(psBMHeap->pVMArena,
+					ppszStr,
+					pui32StrLen);
+	}
+}
+
+/*Level 2 of the loop nesting*/
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
+{
+
+	IMG_UINT32 *pui32StrLen;
+	IMG_INT32 *pi32Count;
+	IMG_CHAR **ppszStr;
+	IMG_UINT32 ui32Mode;
+
+	pui32StrLen = va_arg(va, IMG_UINT32*);
+	pi32Count = va_arg(va, IMG_INT32*);
+	ppszStr = va_arg(va, IMG_CHAR**);
+	ui32Mode = va_arg(va, IMG_UINT32);
+
+	CHECK_SPACE(*pui32StrLen);
+	*pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n",
+							(IMG_HANDLE)psBMContext);
+	UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+	List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
+							&PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+							ppszStr,
+							pui32StrLen,
+							ui32Mode);
+	return PVRSRV_OK;
+}
+
+
+/*level 1 of the loop nesting*/
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+	IMG_UINT32 *pui32StrLen;
+	IMG_INT32 *pi32Count;
+	IMG_CHAR **ppszStr;
+	IMG_UINT32 ui32Mode;
+
+	pui32StrLen = va_arg(va, IMG_UINT32*);
+	pi32Count = va_arg(va, IMG_INT32*);
+	ppszStr = va_arg(va, IMG_CHAR**);
+	ui32Mode = va_arg(va, IMG_UINT32);
+
+	CHECK_SPACE(*pui32StrLen);
+	*pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
+	UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+	/* kernel context: */
+	if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+	{
+		CHECK_SPACE(*pui32StrLen);
+		*pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
+		UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+		List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
+								&PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+								ppszStr,
+								pui32StrLen,
+								ui32Mode);
+	}
+
+	/* double loop app contexts:heaps */
+	return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
+												&PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
+							 					pui32StrLen,
+												pi32Count,
+												ppszStr,
+												ui32Mode);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVGetMiscInfoKM
+
+ @Description
+	Retrieves misc. info.
+
+ @Output PVRSRV_MISC_INFO
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
+{
+	SYS_DATA *psSysData;
+
+	if(!psMiscInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psMiscInfo->ui32StatePresent = 0;
+
+	/* do a basic check for uninitialised request flag */
+	if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
+										|PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+										|PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+										|PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
+										|PVRSRV_MISC_INFO_DDKVERSION_PRESENT
+										|PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
+										|PVRSRV_MISC_INFO_RESET_PRESENT
+										|PVRSRV_MISC_INFO_FREEMEM_PRESENT
+										|PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT
+										|PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT
+										|PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT))
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	SysAcquireData(&psSysData);
+
+	/* return SOC Timer registers */
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
+		(psSysData->pvSOCTimerRegisterKM != IMG_NULL))
+	{
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+		psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
+		psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
+	}
+	else
+	{
+		psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
+		psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
+	}
+
+	/* return SOC Clock Gating registers */
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
+		(psSysData->pvSOCClockGateRegsBase != IMG_NULL))
+	{
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+		psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
+		psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
+	}
+
+	/* memory stats */
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
+		(psMiscInfo->pszMemoryStr != IMG_NULL))
+	{
+		RA_ARENA			**ppArena;
+/*		BM_HEAP				*psBMHeap;
+		BM_CONTEXT			*psBMContext;
+		PVRSRV_DEVICE_NODE	*psDeviceNode;*/
+		IMG_CHAR			*pszStr;
+		IMG_UINT32			ui32StrLen;
+		IMG_INT32			i32Count;
+
+		pszStr = psMiscInfo->pszMemoryStr;
+		ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
+
+		/* Local backing stores */
+		ppArena = &psSysData->apsLocalDevMemArena[0];
+		while(*ppArena)
+		{
+			CHECK_SPACE(ui32StrLen);
+			i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
+			UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+			RA_GetStats(*ppArena,
+							&pszStr,
+							&ui32StrLen);
+			/* advance through the array */
+			ppArena++;
+		}
+
+		/* per device */
+/*		psDeviceNode = psSysData->psDeviceNodeList;*/
+
+		/*triple loop; devices:contexts:heaps*/
+		List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+													&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+													&ui32StrLen,
+													&i32Count,
+													&pszStr,
+													PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
+
+		/* attach a new line and string terminate */
+		i32Count = OSSNPrintf(pszStr, 100, "\n");
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	/* Lean version of mem stats: only show free mem on each RA */
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0)
+		&& psMiscInfo->pszMemoryStr)
+	{
+		IMG_CHAR			*pszStr;
+		IMG_UINT32			ui32StrLen;
+		IMG_INT32			i32Count;
+		
+		pszStr = psMiscInfo->pszMemoryStr;
+		ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+  
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
+
+		/* triple loop over devices:contexts:heaps */
+		List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+													&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+													&ui32StrLen,
+													&i32Count,
+													&pszStr,
+													PVRSRV_MISC_INFO_FREEMEM_PRESENT);
+		
+		i32Count = OSSNPrintf(pszStr, 100, "\n");
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
+		(psSysData->psGlobalEventObject != IMG_NULL))
+	{
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+		psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
+	}
+
+	/* DDK version and memstats not supported in same call to GetMiscInfo */
+
+	if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
+		&& ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
+		&& (psMiscInfo->pszMemoryStr != IMG_NULL))
+	{
+		IMG_CHAR	*pszStr;
+		IMG_UINT32	ui32StrLen;
+		IMG_UINT32 	ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */
+		IMG_INT32	i32Count;
+		IMG_INT i;
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
+
+		/* construct DDK string */
+		psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
+		psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
+		psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI;
+		psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO;
+
+		pszStr = psMiscInfo->pszMemoryStr;
+		ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+		for (i=0; i<4; i++)
+		{
+			if (ui32StrLen < ui32LenStrPerNum)
+			{
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+			i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]);
+			UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+			if (i != 3)
+			{
+				i32Count = OSSNPrintf(pszStr, 2, ".");
+				UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+			}
+		}
+	}
+
+	if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL)
+	{
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT;
+
+		if(psMiscInfo->sCacheOpCtl.bDeferOp)
+		{
+			/* For now, assume deferred ops are "full" cache ops,
+			 * and we don't need (or expect) a meminfo.
+			 */
+			psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
+		}
+		else
+		{
+			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+			PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+			if(!psMiscInfo->sCacheOpCtl.u.hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+						 "Ignoring non-deferred cache op with no meminfo"));
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+			if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE)
+			{
+				PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+						 "Deferred cache op is pending. It is unlikely you want "
+						 "to combine deferred cache ops with immediate ones"));
+			}
+
+			psPerProc = PVRSRVFindPerProcessData();
+
+			if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+								  (IMG_PVOID *)&psKernelMemInfo,
+								  psMiscInfo->sCacheOpCtl.u.hKernelMemInfo,
+								  PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+						 "Can't find kernel meminfo"));
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+			if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+			{
+				if(psMiscInfo->sCacheOpCtl.ui32Length!=0)
+				{
+					if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+											   0,
+											   psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+											   psMiscInfo->sCacheOpCtl.ui32Length))
+					{
+						return PVRSRV_ERROR_CACHEOP_FAILED;
+					}
+				}
+			}
+			else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+			{
+				if(psMiscInfo->sCacheOpCtl.ui32Length!=0)
+				{
+					if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+											   0,
+											   psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+											   psMiscInfo->sCacheOpCtl.ui32Length))
+					{
+						return PVRSRV_ERROR_CACHEOP_FAILED;
+					}
+				}
+			}
+		}
+	}
+
+	if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL)
+	{
+		PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+		PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT;
+
+		psPerProc = PVRSRVFindPerProcessData();
+
+		if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+							  (IMG_PVOID *)&psKernelMemInfo,
+							  psMiscInfo->sGetRefCountCtl.u.hKernelMemInfo,
+							  PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+									"Can't find kernel meminfo"));
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount;
+	}
+
+	if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL)
+	{
+		psMiscInfo->ui32PageSize = HOST_PAGESIZE();
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT;
+	}
+
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+	if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
+	{
+		PVR_LOG(("User requested OS reset"));
+		OSPanic();
+	}
+#endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL)
+	{
+		PVRSRVProcessQueues(IMG_TRUE);
+		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT;
+	}
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDeviceLISR
+
+ @Description
+	OS-independent Device Low-level Interrupt Service Routine
+
+ @Input psDeviceNode
+
+ @Return   IMG_BOOL : Whether any interrupts were serviced
+
+******************************************************************************/
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	SYS_DATA			*psSysData;
+	IMG_BOOL			bStatus = IMG_FALSE;
+	IMG_UINT32			ui32InterruptSource;
+
+	if(!psDeviceNode)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
+		goto out;
+	}
+	psSysData = psDeviceNode->psSysData;
+
+	/* query the SOC/system to see whether this device was the source of the interrupt */
+	ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
+	if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+	{
+		if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+		{
+			bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
+		}
+
+		SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
+	}
+
+out:
+	return bStatus;
+}
+
+static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+
+	IMG_BOOL *pbStatus;
+	IMG_UINT32 *pui32InterruptSource;
+	IMG_UINT32 *pui32ClearInterrupts;
+
+	pbStatus = va_arg(va, IMG_BOOL*);
+	pui32InterruptSource = va_arg(va, IMG_UINT32*);
+	pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
+
+
+	if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+	{
+		if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+		{
+			if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
+			{
+				/* Record if serviced any interrupts. */
+				*pbStatus = IMG_TRUE;
+			}
+			/* Combine the SOC clear bits. */
+			*pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
+		}
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSystemLISR
+
+ @Description
+	OS-independent System Low-level Interrupt Service Routine
+
+ @Input pvSysData
+
+ @Return   IMG_BOOL : Whether any interrupts were serviced
+
+******************************************************************************/
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA			*psSysData = pvSysData;
+	IMG_BOOL			bStatus = IMG_FALSE;
+	IMG_UINT32			ui32InterruptSource;
+	IMG_UINT32			ui32ClearInterrupts = 0;
+/*	PVRSRV_DEVICE_NODE	*psDeviceNode;*/
+
+	if(!psSysData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+/*		goto out; */
+	}
+	else
+	{
+		/* query SOC for source of interrupts */
+		ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
+
+		/* only proceed if PVR interrupts */
+		if(ui32InterruptSource)
+		{
+			/* traverse the devices' ISR handlers */
+			List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+												&PVRSRVSystemLISR_ForEachVaCb,
+												&bStatus,
+												&ui32InterruptSource,
+												&ui32ClearInterrupts);
+
+			SysClearInterrupts(psSysData, ui32ClearInterrupts);
+		}
+/*out:*/
+	}
+	return bStatus;
+}
+
+
+static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
+	{
+		(*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVMISR
+
+ @Input pvSysData
+
+ @Description
+	OS-independent Medium-level Interrupt Service Routine
+
+******************************************************************************/
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA			*psSysData = pvSysData;
+/*	PVRSRV_DEVICE_NODE	*psDeviceNode; */
+
+	if(!psSysData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+		return;
+	}
+
+	/* Traverse the devices' MISR handlers. */
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+									&PVRSRVMISR_ForEachCb);
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	/* Process the queues. */
+	if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
+	{
+		PVRSRVProcessQueues(IMG_FALSE);
+	}
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+	/* signal global event object */
+	if (psSysData->psGlobalEventObject)
+	{
+		IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+		if(hOSEventKM)
+		{
+			OSEventObjectSignalKM(hOSEventKM);
+		}
+	}
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVProcessConnect
+
+ @Description	Inform services that a process has connected.
+
+ @Input		ui32PID - process ID
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32	ui32PID, IMG_UINT32 ui32Flags)
+{
+	return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVProcessDisconnect
+
+ @Description	Inform services that a process has disconnected.
+
+ @Input		ui32PID - process ID
+
+ @Return	IMG_VOID
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32	ui32PID)
+{
+	PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVSaveRestoreLiveSegments
+
+ @Input pArena - the arena the segment was originally allocated from.
+        pbyBuffer - the system memory buffer set to null to get the size needed.
+        puiBufSize - size of system memory buffer.
+        bSave - IMG_TRUE if a save is required
+
+ @Description
+	Function to save or restore Resources Live segments
+
+******************************************************************************/
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
+														IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
+{
+	IMG_SIZE_T         uiBytesSaved = 0;
+	IMG_PVOID          pvLocalMemCPUVAddr;
+	RA_SEGMENT_DETAILS sSegDetails;
+
+	if (hArena == IMG_NULL)
+	{
+		return (PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	sSegDetails.uiSize = 0;
+	sSegDetails.sCpuPhyAddr.uiAddr = 0;
+	sSegDetails.hSegment = 0;
+
+	/* walk the arena segments and write live one to the  buffer */
+	while (RA_GetNextLiveSegment(hArena, &sSegDetails))
+	{
+		if (pbyBuffer == IMG_NULL)
+		{
+			/* calc buffer required */
+			uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+		}
+		else
+		{
+			if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
+			{
+				return (PVRSRV_ERROR_OUT_OF_MEMORY);
+			}
+
+			PVR_DPF((
+                PVR_DBG_MESSAGE, 
+                "PVRSRVSaveRestoreLiveSegments: Base " CPUPADDR_FMT " size %" SIZE_T_FMT_LEN "x", 
+                sSegDetails.sCpuPhyAddr.uiAddr, 
+                sSegDetails.uiSize));
+
+			/* Map the device's local memory area onto the host. */
+			pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
+									sSegDetails.uiSize,
+									PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+									IMG_NULL);
+			if (pvLocalMemCPUVAddr == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
+				return (PVRSRV_ERROR_OUT_OF_MEMORY);
+			}
+
+			if (bSave)
+			{
+				/* write segment size then segment data */
+				OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
+				pbyBuffer += sizeof(sSegDetails.uiSize);
+
+				OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
+				pbyBuffer += sSegDetails.uiSize;
+			}
+			else
+			{
+				IMG_UINT32 uiSize;
+				/* reag segment size and validate */
+				OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
+
+				if (uiSize != sSegDetails.uiSize)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
+				}
+				else
+				{
+					pbyBuffer += sizeof(sSegDetails.uiSize);
+
+					OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
+					pbyBuffer += sSegDetails.uiSize;
+				}
+			}
+
+
+			uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+			OSUnMapPhysToLin(pvLocalMemCPUVAddr,
+		                     sSegDetails.uiSize,
+		                     PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+		                     IMG_NULL);
+		}
+	}
+
+	if (pbyBuffer == IMG_NULL)
+	{
+		*puiBufSize = uiBytesSaved;
+	}
+
+	return (PVRSRV_OK);
+}
+
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVGetErrorStringKM
+
+ @Description	Returns a text string relating to the PVRSRV_ERROR enum.
+
+ @Note		case statement used rather than an indexed arrary to ensure text is
+ 			synchronised with the correct enum
+
+ @Input		eError : PVRSRV_ERROR enum
+
+ @Return	const IMG_CHAR * : Text string
+
+ @Note		Must be kept in sync with servicesext.h
+
+******************************************************************************/
+
+IMG_EXPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
+{ 
+/* PRQA S 5087 1 */ /* include file required here */
+#include "pvrsrv_errors.h"
+}
+
+static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+	{
+		/* Call the device's callback function. */
+		(*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVScheduleDeviceCallbacks
+
+ @Description	Schedule all device callbacks
+
+ @Return	IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
+{
+	SYS_DATA				*psSysData;
+/*	PVRSRV_DEVICE_NODE		*psDeviceNode;*/
+
+	SysAcquireData(&psSysData);
+
+	/*for all the device, invoke the callback function*/
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+									&PVRSRVCommandCompleteCallbacks_ForEachCb);
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVScheduleDevices
+
+ @Description	Schedules all Services-Managed Devices to check their pending
+ 				command queues. The intention is that ScheduleDevices be called by the
+				3rd party BC driver after it has finished writing new data to its output
+				texture.
+
+ @Return	IMG_VOID
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
+{
+	PVRSRVScheduleDeviceCallbacks();
+}
+
+/*****************************************************************************
+ End of file (pvrsrv.c)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/queue.c b/drivers/gpu/pvr/services4/srvkm/common/queue.c
new file mode 100644
index 0000000..c12d5e2
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/queue.c
@@ -0,0 +1,1764 @@
+/*************************************************************************/ /*!
+@Title          Kernel side command queue functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+#include "lists.h"
+#include "ttrace.h"
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
+#include <linux/sw_sync.h>
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0))
+#include <../drivers/staging/android/sw_sync.h>
+#else
+#include <../drivers/dma-buf/sync_debug.h>
+#endif
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include "pvrsrv_sync_server.h"
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#include <linux/list.h>
+#include <linux/workqueue.h>
+
+typedef struct _PVR_QUEUE_SYNC_KERNEL_SYNC_INFO_
+{
+	/* Base services sync info structure */
+	PVRSRV_KERNEL_SYNC_INFO *psBase;
+
+	struct list_head	sHead;
+} PVR_QUEUE_SYNC_KERNEL_SYNC_INFO;
+
+static IMG_BOOL PVRSyncIsSyncInfoInUse(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo)
+{
+	return !(psSyncInfo->psSyncData->ui32WriteOpsPending == psSyncInfo->psSyncData->ui32WriteOpsComplete &&
+			psSyncInfo->psSyncData->ui32ReadOpsPending == psSyncInfo->psSyncData->ui32ReadOpsComplete &&
+			psSyncInfo->psSyncData->ui32ReadOps2Pending == psSyncInfo->psSyncData->ui32ReadOps2Complete);
+}
+
+/* Defer Workqueue for releasing command kernel sync info */
+static struct workqueue_struct *gpsWorkQueue;
+
+/* Linux work struct for workqueue. */
+static struct work_struct gsWork;
+
+/* The "defer-free" sync object list. */
+static LIST_HEAD(gSyncInfoFreeList);
+static DEFINE_SPINLOCK(gSyncInfoFreeListLock);
+
+static void PVRSyncWorkQueueFunction(struct work_struct *data)
+{
+	struct list_head sFreeList, *psEntry, *n;
+	PVR_QUEUE_SYNC_KERNEL_SYNC_INFO *psSyncInfo;
+
+	INIT_LIST_HEAD(&sFreeList);
+	spin_lock(&gSyncInfoFreeListLock);
+	list_for_each_safe(psEntry, n, &gSyncInfoFreeList)
+	{
+		psSyncInfo = container_of(psEntry, PVR_QUEUE_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		if(!PVRSyncIsSyncInfoInUse(psSyncInfo->psBase))
+			list_move_tail(psEntry, &sFreeList);
+    	}
+	spin_unlock(&gSyncInfoFreeListLock);
+
+	list_for_each_safe(psEntry, n, &sFreeList)
+	{
+		psSyncInfo = container_of(psEntry, PVR_QUEUE_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		list_del(psEntry);
+
+		PVRSRVKernelSyncInfoDecRef(psSyncInfo->psBase, IMG_NULL);
+	}
+}
+#endif
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+static struct sync_fence *AllocQueueFence(struct sw_sync_timeline *psTimeline, IMG_UINT32 ui32FenceValue, const char *szName)
+{
+	struct sync_fence *psFence = IMG_NULL;
+	struct sync_pt *psPt;
+
+	psPt = sw_sync_pt_create(psTimeline, ui32FenceValue);
+	if(psPt)
+	{
+		psFence = sync_fence_create(szName, psPt);
+		if(!psFence)
+		{
+			sync_pt_free(psPt);
+		}
+	}
+
+	return psFence;
+}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE) */
+
+/*
+ * The number of commands of each type which can be in flight at once.
+ */
+
+#define DC_MAX_SUPPORTED_QUEUES			1
+#if defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+#define DC_NUM_COMMANDS_PER_QUEUE		2
+#else
+#define DC_NUM_COMMANDS_PER_QUEUE		1
+#endif
+
+#define DC_NUM_COMMANDS_PER_TYPE (DC_NUM_COMMANDS_PER_QUEUE * DC_MAX_SUPPORTED_QUEUES)
+
+static IMG_UINT32 ui32NoOfSwapchainCreated = 0;
+
+/*
+ * List of private command processing function pointer tables and command
+ * complete tables for a device in the system.
+ * Each table is allocated when the device registers its private command
+ * processing functions.
+ */
+typedef struct _DEVICE_COMMAND_DATA_
+{
+	PFN_CMD_PROC			pfnCmdProc;
+	PCOMMAND_COMPLETE_DATA	apsCmdCompleteData[DC_NUM_COMMANDS_PER_TYPE];
+	IMG_UINT32				ui32CCBOffset;
+	IMG_UINT32				ui32MaxDstSyncCount;	/*!< Maximum number of dest syncs */
+	IMG_UINT32				ui32MaxSrcSyncCount;	/*!< Maximum number of source syncs */
+} DEVICE_COMMAND_DATA;
+
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#include "proc.h"
+
+/*****************************************************************************
+ FUNCTION	:	ProcSeqShowQueue
+
+ PURPOSE	:	Print the content of queue element  to /proc file
+				(See env/linux/proc.c:CreateProcReadEntrySeq)
+
+ PARAMETERS	:	sfile - /proc seq_file
+				el - Element to print
+*****************************************************************************/
+void ProcSeqShowQueue(struct seq_file *sfile,void* el)
+{
+	PVRSRV_QUEUE_INFO *psQueue = (PVRSRV_QUEUE_INFO*)el;
+	IMG_INT cmds = 0;
+	IMG_SIZE_T uReadOffset;
+	IMG_SIZE_T uWriteOffset;
+	PVRSRV_COMMAND *psCmd;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf( sfile,
+					"Command Queues\n"
+					"Queue    CmdPtr      Pid Command Size DevInd  DSC  SSC  #Data ...\n");
+		return;
+	}
+
+	uReadOffset = psQueue->uReadOffset;
+	uWriteOffset = psQueue->uWriteOffset;
+
+	while (uReadOffset != uWriteOffset)
+	{
+		psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + uReadOffset);
+
+		seq_printf(sfile, "%p %p  %5u  %6u  %3" SIZE_T_FMT_LEN "u  %5u   %2u   %2u    %3" SIZE_T_FMT_LEN "u  \n",
+							psQueue,
+							psCmd,
+					 		psCmd->ui32ProcessID,
+							psCmd->CommandType,
+							psCmd->uCmdSize,
+							psCmd->ui32DevIndex,
+							psCmd->ui32DstSyncCount,
+							psCmd->ui32SrcSyncCount,
+							psCmd->uDataSize);
+		{
+			IMG_UINT32 i;
+			for (i = 0; i < psCmd->ui32SrcSyncCount; i++)
+			{
+				PVRSRV_SYNC_DATA *psSyncData = psCmd->psSrcSync[i].psKernelSyncInfoKM->psSyncData;
+				seq_printf(sfile, "  Sync %u: ROP/ROC: 0x%x/0x%x WOP/WOC: 0x%x/0x%x ROC-VA: 0x%x WOC-VA: 0x%x\n",
+									i,
+									psCmd->psSrcSync[i].ui32ReadOps2Pending,
+									psSyncData->ui32ReadOps2Complete,
+									psCmd->psSrcSync[i].ui32WriteOpsPending,
+									psSyncData->ui32WriteOpsComplete,
+									psCmd->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+									psCmd->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr);
+			}
+		}
+
+		/* taken from UPDATE_QUEUE_ROFF in queue.h */
+		uReadOffset += psCmd->uCmdSize;
+		uReadOffset &= psQueue->uQueueSize - 1;
+		cmds++;
+	}
+
+	if (cmds == 0)
+	{
+		seq_printf(sfile, "%p <empty>\n", psQueue);
+	}
+}
+
+/*****************************************************************************
+ FUNCTION	:	ProcSeqOff2ElementQueue
+
+ PURPOSE	:	Transale offset to element (/proc stuff)
+
+ PARAMETERS	:	sfile - /proc seq_file
+				off - the offset into the buffer
+
+ RETURNS    :   element to print
+*****************************************************************************/
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
+{
+	PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+	SYS_DATA *psSysData;
+
+	PVR_UNREFERENCED_PARAMETER(sfile);
+
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+
+	psSysData = SysAcquireDataNoCheck();
+	if (psSysData != IMG_NULL)
+	{
+		for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM);
+	}
+
+	return psQueue;
+}
+#endif /* __linux__ && __KERNEL__ */
+
+/*!
+ * Macro to return space in given command queue
+ */
+#define GET_SPACE_IN_CMDQ(psQueue)										\
+	((((psQueue)->uReadOffset - (psQueue)->uWriteOffset)				\
+	+ ((psQueue)->uQueueSize - 1)) & ((psQueue)->uQueueSize - 1))
+
+/*!
+ * Macro to Write Offset in given command queue
+ */
+#define UPDATE_QUEUE_WOFF(psQueue, uSize)							\
+	(psQueue)->uWriteOffset = ((psQueue)->uWriteOffset + (uSize))	\
+	& ((psQueue)->uQueueSize - 1);
+
+/*!
+ * Check if an ops complete value has gone past the pending value.
+ * This can happen when dummy processing multiple operations, e.g. hardware recovery.
+ */
+#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending)					\
+	((ui32OpsComplete) >= (ui32OpsPending))
+
+/*!
+****************************************************************************
+ @Function	: PVRSRVGetWriteOpsPending
+
+ @Description	: Gets the next operation to wait for in a sync object
+
+ @Input	: psSyncInfo	- pointer to sync information struct
+ @Input	: bIsReadOp		- Is this a read or write op
+
+ @Return : Next op value
+*****************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetWriteOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetWriteOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+	IMG_UINT32 ui32WriteOpsPending;
+
+	if(bIsReadOp)
+	{
+		ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+	else
+	{
+		/*
+			Note: This needs to be atomic and is provided the
+			kernel driver is single threaded (non-rentrant)
+		*/
+		ui32WriteOpsPending = SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_QUEUE);
+	}
+
+	return ui32WriteOpsPending;
+}
+
+/*!
+*****************************************************************************
+ @Function	: PVRSRVGetReadOpsPending
+
+ @Description	: Gets the number of pending read ops
+
+ @Input	: psSyncInfo	- pointer to sync information struct
+ @Input : bIsReadOp		- Is this a read or write op
+
+ @Return : Next op value
+*****************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetReadOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+	IMG_UINT32 ui32ReadOpsPending;
+
+	if(bIsReadOp)
+	{
+		ui32ReadOpsPending = SyncTakeReadOp2(psSyncInfo, SYNC_OP_CLASS_QUEUE);
+	}
+	else
+	{
+		ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+	}
+
+	return ui32ReadOpsPending;
+}
+
+static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
+									 IMG_UINT32				i,
+									 IMG_BOOL				bIsSrc)
+{
+	PVRSRV_SYNC_OBJECT	*psSyncObject;
+
+	psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync;
+
+	if (psCmdCompleteData->bInUse)
+	{
+		PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x",
+				bIsSrc ? "SRC" : "DEST", i,
+				psSyncObject[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Pending,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete,
+				psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
+				psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete))
+	}
+	else
+	{
+		PVR_LOG(("\t%s %u: (Not in use)", bIsSrc ? "SRC" : "DEST", i))
+	}
+}
+
+
+static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+	{
+		IMG_UINT32				ui32CmdCounter, ui32SyncCounter;
+		SYS_DATA				*psSysData;
+		DEVICE_COMMAND_DATA		*psDeviceCommandData;
+		PCOMMAND_COMPLETE_DATA	psCmdCompleteData;
+
+		SysAcquireData(&psSysData);
+
+		psDeviceCommandData = psSysData->apsDeviceCommandData[psDeviceNode->sDevId.ui32DeviceIndex];
+
+		if (psDeviceCommandData != IMG_NULL)
+		{
+			for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+			{
+				psCmdCompleteData = psDeviceCommandData[DC_FLIP_COMMAND].apsCmdCompleteData[ui32CmdCounter];
+
+				PVR_LOG(("Flip Command Complete Data %u for display device %u:",
+						ui32CmdCounter, psDeviceNode->sDevId.ui32DeviceIndex))
+
+				for (ui32SyncCounter = 0;
+					 ui32SyncCounter < psCmdCompleteData->ui32SrcSyncCount;
+					 ui32SyncCounter++)
+				{
+					QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_TRUE);
+				}
+
+				for (ui32SyncCounter = 0;
+					 ui32SyncCounter < psCmdCompleteData->ui32DstSyncCount;
+					 ui32SyncCounter++)
+				{
+					QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_FALSE);
+				}
+			}
+		}
+		else
+		{
+			PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex))
+		}
+	}
+}
+
+
+IMG_VOID QueueDumpDebugInfo(IMG_VOID)
+{
+	SYS_DATA	*psSysData;
+	SysAcquireData(&psSysData);
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &QueueDumpDebugInfo_ForEachCb);
+}
+
+
+/*****************************************************************************
+	Kernel-side functions of User->Kernel transitions
+******************************************************************************/
+
+static IMG_SIZE_T NearestPower2(IMG_SIZE_T uValue)
+{
+	IMG_SIZE_T uTemp, uResult = 1;
+
+	if(!uValue)
+		return 0;
+
+	uTemp = uValue - 1;
+	while(uTemp)
+	{
+		uResult <<= 1;
+		uTemp >>= 1;
+	}
+
+	return uResult;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVCreateCommandQueueKM
+
+ @Description
+ Creates a new command queue into which render/blt commands etc can be
+ inserted.
+
+ @Input    uQueueSize :
+
+ @Output   ppsQueueInfo :
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T uQueueSize,
+													 PVRSRV_QUEUE_INFO **ppsQueueInfo)
+{
+	PVRSRV_QUEUE_INFO	*psQueueInfo;
+	IMG_SIZE_T			uPower2QueueSize = NearestPower2(uQueueSize);
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+	IMG_HANDLE			hMemBlock;
+
+	if (ui32NoOfSwapchainCreated >= DC_NUM_COMMANDS_PER_TYPE)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Swapchain already exists, increment DC_MAX_SUPPORTED_QUEUES to support more than one swapchain"));
+		return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+	}
+
+	SysAcquireData(&psSysData);
+
+	/* allocate an internal queue info structure */
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_QUEUE_INFO),
+					 (IMG_VOID **)&psQueueInfo, &hMemBlock,
+					 "Queue Info");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
+		goto ErrorExit;
+	}
+	OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
+
+	psQueueInfo->hMemBlock[0] = hMemBlock;
+	psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+	/* allocate the command queue buffer - allow for overrun */
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 uPower2QueueSize + PVRSRV_MAX_CMD_SIZE,
+					 &psQueueInfo->pvLinQueueKM, &hMemBlock,
+					 "Command Queue");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
+		goto ErrorExit;
+	}
+
+	psQueueInfo->hMemBlock[1] = hMemBlock;
+	psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
+
+	/* Sanity check: Should be zeroed by OSMemSet */
+	PVR_ASSERT(psQueueInfo->uReadOffset == 0);
+	PVR_ASSERT(psQueueInfo->uWriteOffset == 0);
+
+	psQueueInfo->uQueueSize = uPower2QueueSize;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	psQueueInfo->pvTimeline = sw_sync_timeline_create("pvr_queue_proc");
+	if(psQueueInfo->pvTimeline == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: sw_sync_timeline_create() failed"));
+		goto ErrorExit;
+	}
+#endif
+
+	/* if this is the first q, create a lock resource for the q list */
+	if (psSysData->psQueueList == IMG_NULL)
+	{
+		eError = OSCreateResource(&psSysData->sQProcessResource);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+	/* Ensure we don't corrupt queue list, by blocking access */
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	eError = OSLockResourceAndBlockMISR(&psSysData->sQProcessResource,
+							KERNEL_ID);
+#else /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	eError = OSLockResource(&psSysData->sQProcessResource,
+							KERNEL_ID);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	if (eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	psQueueInfo->psNextKM = psSysData->psQueueList;
+	psSysData->psQueueList = psQueueInfo;
+
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	eError = OSUnlockResourceAndUnblockMISR(&psSysData->sQProcessResource, KERNEL_ID);
+#else /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	if (eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	*ppsQueueInfo = psQueueInfo;
+
+#if (defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	if(!ui32NoOfSwapchainCreated)
+	{
+		gpsWorkQueue = create_freezable_workqueue("flip_pvr_sync_workqueue");
+		if(!gpsWorkQueue)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create flip_pvr_sync workqueue", __func__));
+			goto ErrorExit;
+		}
+		INIT_WORK(&gsWork, PVRSyncWorkQueueFunction);
+	}
+#endif
+	ui32NoOfSwapchainCreated++;
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	if(psQueueInfo)
+	{
+		if(psQueueInfo->pvLinQueueKM)
+		{
+			OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+						psQueueInfo->uQueueSize,
+						psQueueInfo->pvLinQueueKM,
+						psQueueInfo->hMemBlock[1]);
+			psQueueInfo->pvLinQueueKM = IMG_NULL;
+		}
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					sizeof(PVRSRV_QUEUE_INFO),
+					psQueueInfo,
+					psQueueInfo->hMemBlock[0]);
+		/*not nulling pointer, out of scope*/
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDestroyCommandQueueKM
+
+ @Description	Destroys a command queue
+
+ @Input		psQueueInfo :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
+{
+	PVRSRV_QUEUE_INFO	*psQueue;
+	SYS_DATA			*psSysData;
+	PVRSRV_ERROR		eError;
+	IMG_BOOL			bTimeout = IMG_TRUE;
+
+	SysAcquireData(&psSysData);
+
+	psQueue = psSysData->psQueueList;
+
+	/* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if(psQueueInfo->uReadOffset == psQueueInfo->uWriteOffset)
+		{
+			bTimeout = IMG_FALSE;
+			break;
+		}
+		OSSleepms(1);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	if (bTimeout)
+	{
+		/* The command queue could not be flushed within the timeout period.
+		Allow the queue to be destroyed before returning the error code. */
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+		eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+		goto ErrorExit;
+	}
+
+	/* Ensure we don't corrupt queue list, by blocking access */
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	eError = OSLockResourceAndBlockMISR(&psSysData->sQProcessResource,
+								KERNEL_ID);
+#else /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	eError = OSLockResource(&psSysData->sQProcessResource,
+								KERNEL_ID);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	if (eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	ui32NoOfSwapchainCreated--;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	sync_timeline_destroy(psQueueInfo->pvTimeline);
+#endif
+
+	if(psQueue == psQueueInfo)
+	{
+		psSysData->psQueueList = psQueueInfo->psNextKM;
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					NearestPower2(psQueueInfo->uQueueSize) + PVRSRV_MAX_CMD_SIZE,
+					psQueueInfo->pvLinQueueKM,
+					psQueueInfo->hMemBlock[1]);
+		psQueueInfo->pvLinQueueKM = IMG_NULL;
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					sizeof(PVRSRV_QUEUE_INFO),
+					psQueueInfo,
+					psQueueInfo->hMemBlock[0]);
+		/* PRQA S 3199 1 */ /* see note */
+		psQueueInfo = IMG_NULL; /*it's a copy on stack, but null it because the function doesn't end right here*/
+	}
+	else
+	{
+		while(psQueue)
+		{
+			if(psQueue->psNextKM == psQueueInfo)
+			{
+				psQueue->psNextKM = psQueueInfo->psNextKM;
+
+				OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+							psQueueInfo->uQueueSize,
+							psQueueInfo->pvLinQueueKM,
+							psQueueInfo->hMemBlock[1]);
+				psQueueInfo->pvLinQueueKM = IMG_NULL;
+				OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+							sizeof(PVRSRV_QUEUE_INFO),
+							psQueueInfo,
+							psQueueInfo->hMemBlock[0]);
+				/* PRQA S 3199 1 */ /* see note */
+				psQueueInfo = IMG_NULL; /*it's a copy on stack, but null it because the function doesn't end right here*/
+				break;
+			}
+			psQueue = psQueue->psNextKM;
+		}
+
+		if(!psQueue)
+		{
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+			eError = OSUnlockResourceAndUnblockMISR(&psSysData->sQProcessResource, KERNEL_ID);
+#else /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+			eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+			if (eError != PVRSRV_OK)
+			{
+				goto ErrorExit;
+			}
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto ErrorExit;
+		}
+	}
+
+	/*  unlock the Q list lock resource */
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	eError = OSUnlockResourceAndUnblockMISR(&psSysData->sQProcessResource, KERNEL_ID);
+#else /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	if (eError != PVRSRV_OK)
+	{
+		goto ErrorExit;
+	}
+
+	/*  if the Q list is now empty, destroy the Q list lock resource */
+	if (psSysData->psQueueList == IMG_NULL)
+	{
+		eError = OSDestroyResource(&psSysData->sQProcessResource);
+		if (eError != PVRSRV_OK)
+		{
+			goto ErrorExit;
+		}
+	}
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	if(!ui32NoOfSwapchainCreated && gpsWorkQueue)
+	{
+		destroy_workqueue(gpsWorkQueue);
+	}
+#endif
+ErrorExit:
+
+	return eError;
+}
+
+
+/*!
+*****************************************************************************
+
+ @Function	: PVRSRVGetQueueSpaceKM
+
+ @Description	: Waits for queue access rights and checks for available space in
+			  queue for task param structure
+
+ @Input	: psQueue	   	- pointer to queue information struct
+ @Input : ui32ParamSize - size of task data structure
+ @Output : ppvSpace
+
+ @Return	: PVRSRV_ERROR
+*****************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+												IMG_SIZE_T uParamSize,
+												IMG_VOID **ppvSpace)
+{
+	/*	round to 4byte units */
+	uParamSize =  (uParamSize + 3) & 0xFFFFFFFC;
+
+	if (uParamSize > PVRSRV_MAX_CMD_SIZE)
+	{
+		PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
+		return PVRSRV_ERROR_CMD_TOO_BIG;
+	}
+
+	if (GET_SPACE_IN_CMDQ(psQueue) > uParamSize)
+	{
+		*ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->uWriteOffset);
+	}
+	else
+	{
+		*ppvSpace = IMG_NULL;
+		return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+*****************************************************************************
+ @Function	PVRSRVInsertCommandKM
+
+ @Description :
+			command insertion utility
+			 - waits for space in the queue for a new command
+			 - fills in generic command information
+			 - returns a pointer to the caller who's expected to then fill
+			 	in the private data.
+			The caller should follow PVRSRVInsertCommand with PVRSRVSubmitCommand
+			which will update the queue's write offset so the command can be
+			executed.
+
+ @Input		psQueue : pointer to queue information struct
+
+ @Output	ppvCmdData : holds pointer to space in queue for private cmd data
+
+ @Return	PVRSRV_ERROR
+*****************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO	*psQueue,
+												PVRSRV_COMMAND		**ppsCommand,
+												IMG_UINT32			ui32DevIndex,
+												IMG_UINT16			CommandType,
+												IMG_UINT32			ui32DstSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsDstSync[],
+												IMG_UINT32			ui32SrcSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsSrcSync[],
+												IMG_SIZE_T			uDataByteSize,
+												PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+												IMG_HANDLE			hCallbackData,
+												IMG_HANDLE			*phFence)
+{
+	PVRSRV_ERROR 	eError;
+	PVRSRV_COMMAND	*psCommand;
+	IMG_SIZE_T		uCommandSize;
+	IMG_UINT32		i;
+	SYS_DATA *psSysData;
+	DEVICE_COMMAND_DATA *psDeviceCommandData;
+
+#if !(defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE))
+	PVR_UNREFERENCED_PARAMETER(phFence);
+#endif
+
+	/* Check that we've got enough space in our command complete data for this command */
+	SysAcquireData(&psSysData);
+	psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+
+	if ((psDeviceCommandData[CommandType].ui32MaxDstSyncCount < ui32DstSyncCount) ||
+	   (psDeviceCommandData[CommandType].ui32MaxSrcSyncCount < ui32SrcSyncCount))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: Too many syncs"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* Round up to nearest 32 bit size so pointer arithmetic works */
+	uDataByteSize = (uDataByteSize + 3UL) & ~3UL;
+
+	/*  calc. command size */
+	uCommandSize = sizeof(PVRSRV_COMMAND)
+					+ ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+					+ uDataByteSize;
+
+	/* wait for space in queue */
+	eError = PVRSRVGetQueueSpaceKM (psQueue, uCommandSize, (IMG_VOID**)&psCommand);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	if(phFence != IMG_NULL)
+	{
+		struct sync_fence *psRetireFence, *psCleanupFence;
+
+		/* New command? New timeline target */
+		psQueue->ui32FenceValue++;
+
+		psRetireFence = AllocQueueFence(psQueue->pvTimeline, psQueue->ui32FenceValue, "pvr_queue_retire");
+		if(!psRetireFence)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: sync_fence_create() failed"));
+			psQueue->ui32FenceValue--;
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		/* This similar to the retire fence, except that it is destroyed
+		 * when a display command completes, rather than at the whim of
+		 * userspace. It is used to keep the timeline alive.
+		 */
+		psCleanupFence = AllocQueueFence(psQueue->pvTimeline, psQueue->ui32FenceValue, "pvr_queue_cleanup");
+		if(!psCleanupFence)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: sync_fence_create() #2 failed"));
+			sync_fence_put(psRetireFence);
+			psQueue->ui32FenceValue--;
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		psCommand->pvCleanupFence = psCleanupFence;
+		psCommand->pvTimeline = psQueue->pvTimeline;
+		*phFence = psRetireFence;
+	}
+	else
+	{
+		psCommand->pvTimeline = IMG_NULL;
+		psCommand->pvCleanupFence = IMG_NULL;
+	}
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	if(phFence != IMG_NULL)
+	{
+		struct fence *psRetireFence, *psCleanupFence;
+
+		SyncSWGetTimelineObj(psQueue->i32TimelineFd, &psCommand->pvTimeline);
+		if(psCommand->pvTimeline == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"PVRSRVInsertCommandKM: timeline get failed"));
+			return PVRSRV_ERROR_STREAM_ERROR;
+		}
+
+		/* New command? New timeline target */
+		psQueue->ui32FenceValue++;
+
+		psRetireFence = SyncSWTimelineFenceCreateKM(psQueue->i32TimelineFd, psQueue->ui32FenceValue, "pvr_queue_retire");
+		if(!psRetireFence)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: sync_file_create() failed"));
+			psQueue->ui32FenceValue--;
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		/* This similar to the retire fence, except that it is destroyed
+		 * when a display command completes, rather than at the whim of
+		 * userspace. It is used to keep the timeline alive.
+		 */
+		psCleanupFence = SyncSWTimelineFenceCreateKM(psQueue->i32TimelineFd, psQueue->ui32FenceValue, "pvr_queue_cleanup");
+		if(!psCleanupFence)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: sync_file_create() #2 failed"));
+			SyncSWTimelineFenceReleaseKM(psRetireFence);
+			psQueue->ui32FenceValue--;
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+
+		psCommand->pvCleanupFence = psCleanupFence;
+		*phFence = psRetireFence;
+	}
+	else
+	{
+		psCommand->pvTimeline = IMG_NULL;
+		psCommand->pvCleanupFence = IMG_NULL;
+	}
+
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+	psCommand->ui32ProcessID	= OSGetCurrentProcessIDKM();
+
+	/* setup the command */
+	psCommand->uCmdSize			= uCommandSize; /* this may change if cmd shrinks */
+	psCommand->ui32DevIndex 	= ui32DevIndex;
+	psCommand->CommandType 		= CommandType;
+	psCommand->ui32DstSyncCount	= ui32DstSyncCount;
+	psCommand->ui32SrcSyncCount	= ui32SrcSyncCount;
+	/* override QAC warning about stricter pointers */
+	/* PRQA S 3305 END_PTR_ASSIGNMENTS */
+	psCommand->psDstSync		= (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
+
+
+	psCommand->psSrcSync		= (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync)
+								+ (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+	psCommand->pvData			= (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+								+ (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+/* PRQA L:END_PTR_ASSIGNMENTS */
+
+	psCommand->uDataSize		= uDataByteSize;/* this may change if cmd shrinks */
+
+	psCommand->pfnCommandComplete = pfnCommandComplete;
+	psCommand->hCallbackData = hCallbackData;
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_START, QUEUE_TOKEN_INSERTKM);
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_NONE,
+			QUEUE_TOKEN_COMMAND_TYPE, CommandType);
+
+	/* setup dst sync objects and their sync dependencies */
+	for (i=0; i<ui32DstSyncCount; i++)
+	{
+#if (defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+		PVR_QUEUE_SYNC_KERNEL_SYNC_INFO *psQueueSync = (PVR_QUEUE_SYNC_KERNEL_SYNC_INFO*)kmalloc(sizeof(PVR_QUEUE_SYNC_KERNEL_SYNC_INFO),GFP_KERNEL);
+		psQueueSync->psBase = apsDstSync[i];
+		spin_lock(&gSyncInfoFreeListLock);
+		list_add_tail(&psQueueSync->sHead, &gSyncInfoFreeList);
+		spin_unlock(&gSyncInfoFreeListLock);
+#endif
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
+						apsDstSync[i], PVRSRV_SYNCOP_SAMPLE);
+
+		psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
+		psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
+		psCommand->psDstSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+		PVRSRVKernelSyncInfoIncRef(apsDstSync[i], IMG_NULL);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+				i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+				psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCommand->psDstSync[i].ui32ReadOps2Pending,
+				psCommand->psDstSync[i].ui32WriteOpsPending));
+	}
+
+	/* setup src sync objects and their sync dependencies */
+	for (i=0; i<ui32SrcSyncCount; i++)
+	{
+#if (defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+		PVR_QUEUE_SYNC_KERNEL_SYNC_INFO *psQueueSync = (PVR_QUEUE_SYNC_KERNEL_SYNC_INFO*)kmalloc(sizeof(PVR_QUEUE_SYNC_KERNEL_SYNC_INFO),GFP_KERNEL);
+		psQueueSync->psBase = apsSrcSync[i];
+		spin_lock(&gSyncInfoFreeListLock);
+		list_add_tail(&psQueueSync->sHead, &gSyncInfoFreeList);
+		spin_unlock(&gSyncInfoFreeListLock);
+#endif
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
+						apsSrcSync[i], PVRSRV_SYNCOP_SAMPLE);
+
+		psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+		psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
+		psCommand->psSrcSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+		PVRSRVKernelSyncInfoIncRef(apsSrcSync[i], IMG_NULL);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+				i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+				psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCommand->psSrcSync[i].ui32ReadOps2Pending,
+				psCommand->psSrcSync[i].ui32WriteOpsPending));
+	}
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_END, QUEUE_TOKEN_INSERTKM);
+
+	/* return pointer to caller to fill out private data */
+	*ppsCommand = psCommand;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+*******************************************************************************
+ @Function	: PVRSRVSubmitCommandKM
+
+ @Description :
+ 			 updates the queue's write offset so the command can be executed.
+
+ @Input	: psQueue 		-	queue command is in
+ @Input	: psCommand
+
+ @Return : PVRSRV_ERROR
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+												PVRSRV_COMMAND *psCommand)
+{
+	/* override QAC warnings about stricter pointers */
+	/* PRQA S 3305 END_PTR_ASSIGNMENTS2 */
+	/* patch pointers in the command to be kernel pointers */
+	if (psCommand->ui32DstSyncCount > 0)
+	{
+		psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+									+ psQueue->uWriteOffset + sizeof(PVRSRV_COMMAND));
+	}
+
+	if (psCommand->ui32SrcSyncCount > 0)
+	{
+		psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+									+ psQueue->uWriteOffset + sizeof(PVRSRV_COMMAND)
+									+ (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+	}
+
+	psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+									+ psQueue->uWriteOffset + sizeof(PVRSRV_COMMAND)
+									+ (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+									+ (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+/* PRQA L:END_PTR_ASSIGNMENTS2 */
+
+	/* update write offset before releasing access lock */
+	UPDATE_QUEUE_WOFF(psQueue, psCommand->uCmdSize);
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	CheckIfSyncIsQueued
+
+ @Description	Check if the specificed sync object is already queued and
+                can safely be given to the display controller.
+                This check is required as a 3rd party displayclass device can
+                have several flips "in flight" and we need to ensure that we
+                keep their pipeline full and don't deadlock waiting for them
+                to complete an operation on a surface.
+
+ @Input		psSysData : system data
+ @Input		psCmdData : COMMAND_COMPLETE_DATA structure
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR CheckIfSyncIsQueued(PVRSRV_SYNC_OBJECT *psSync, COMMAND_COMPLETE_DATA *psCmdData)
+{
+	IMG_UINT32 k;
+ 
+	if (psCmdData->bInUse)
+	{
+		for (k=0;k<psCmdData->ui32SrcSyncCount;k++)
+		{
+			if (psSync->psKernelSyncInfoKM == psCmdData->psSrcSync[k].psKernelSyncInfoKM)
+			{
+				PVRSRV_SYNC_DATA *psSyncData = psSync->psKernelSyncInfoKM->psSyncData;
+				IMG_UINT32 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+				/*
+					We still need to ensure that we don't we don't give a command
+					to the display controller if writes are outstanding on it
+				*/
+				if (ui32WriteOpsComplete == psSync->ui32WriteOpsPending)
+				{
+					return PVRSRV_OK;
+				}
+				else
+				{
+					if (SYNCOPS_STALE(ui32WriteOpsComplete, psSync->ui32WriteOpsPending))
+					{
+						PVR_DPF((PVR_DBG_WARNING,
+								"CheckIfSyncIsQueued: Stale syncops psSyncData:0x%p ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+								psSyncData, ui32WriteOpsComplete, psSync->ui32WriteOpsPending));
+						return PVRSRV_OK;
+					}
+				}
+			}
+		}
+	}
+	return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVProcessCommand
+
+ @Description	Tries to process a command
+
+ @Input		psSysData : system data
+ @Input		psCommand : PVRSRV_COMMAND structure
+ @Input		bFlush : Check for stale dependencies (only used for HW recovery)
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA			*psSysData,
+								  PVRSRV_COMMAND	*psCommand,
+								  IMG_BOOL			bFlush)
+{
+	PVRSRV_SYNC_OBJECT		*psWalkerObj;
+	PVRSRV_SYNC_OBJECT		*psEndObj;
+	IMG_UINT32				i;
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData;
+	PVRSRV_ERROR			eError = PVRSRV_OK;
+	IMG_UINT32				ui32WriteOpsComplete;
+	IMG_UINT32				ui32ReadOpsComplete;
+	DEVICE_COMMAND_DATA		*psDeviceCommandData;
+	IMG_UINT32				ui32CCBOffset;
+
+	/* satisfy sync dependencies on the DST(s) */
+	psWalkerObj = psCommand->psDstSync;
+	psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+	while (psWalkerObj < psEndObj)
+	{
+		PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+		ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+		ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
+		/* fail if reads or writes are not up to date */
+		if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+		||	(ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
+		{
+			if (!bFlush ||
+				!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+				!SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
+			{
+				return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+			}
+		}
+
+		psWalkerObj++;
+	}
+
+	/* satisfy sync dependencies on the SRC(s) */
+	psWalkerObj = psCommand->psSrcSync;
+	psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
+	while (psWalkerObj < psEndObj)
+	{
+		PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+		ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
+		ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+		/* fail if writes are not up to date */
+		if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+		|| (ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
+		{
+			if (!bFlush &&
+				SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
+				SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
+			{
+				PVR_DPF((PVR_DBG_WARNING,
+						"PVRSRVProcessCommand: Stale syncops psSyncData:0x%p ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+						psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending));
+			}
+
+			if (!bFlush ||
+				!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+				!SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
+			{
+				IMG_UINT32 j;
+				PVRSRV_ERROR eError;
+				IMG_BOOL bFound = IMG_FALSE;
+
+				psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+				for (j=0;j<DC_NUM_COMMANDS_PER_TYPE;j++)
+				{
+					eError = CheckIfSyncIsQueued(psWalkerObj, psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[j]);
+
+					if (eError == PVRSRV_OK)
+					{
+						bFound = IMG_TRUE;
+					}
+				}
+				if (!bFound)
+					return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+			}
+		}
+		psWalkerObj++;
+	}
+
+	/* validate device type */
+	if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+					"PVRSRVProcessCommand: invalid DeviceType 0x%x",
+					psCommand->ui32DevIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* fish out the appropriate storage structure for the duration of the command */
+	psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+	ui32CCBOffset = psDeviceCommandData[psCommand->CommandType].ui32CCBOffset;
+	psCmdCompleteData = psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[ui32CCBOffset];
+	if (psCmdCompleteData->bInUse)
+	{
+		/* can use this to protect against concurrent execution of same command */
+		return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+	}
+
+	/* mark the structure as in use */
+	psCmdCompleteData->bInUse = IMG_TRUE;
+
+	/* copy src updates over */
+	psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+	for (i=0; i<psCommand->ui32DstSyncCount; i++)
+	{
+		psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+				i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
+				psCmdCompleteData->psDstSync[i].ui32WriteOpsPending,
+				ui32CCBOffset));
+	}
+
+	psCmdCompleteData->pfnCommandComplete = psCommand->pfnCommandComplete;
+	psCmdCompleteData->hCallbackData = psCommand->hCallbackData;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	psCmdCompleteData->pvCleanupFence = psCommand->pvCleanupFence;
+	psCmdCompleteData->pvTimeline = psCommand->pvTimeline;
+#endif
+
+	/* copy dst updates over */
+	psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+	for (i=0; i<psCommand->ui32SrcSyncCount; i++)
+	{
+		psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+				i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
+				psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending,
+				ui32CCBOffset));
+	}
+
+	/*
+		call the cmd specific handler:
+		it should:
+		 - check the cmd specific dependencies
+		 - setup private cmd complete structure
+		 - execute cmd on HW
+		 - store psCmdCompleteData `cookie' and later pass as
+			argument to Generic Command Complete Callback
+
+		n.b. ui32DataSize (packet size) is useful for packet validation
+	*/
+	if (psDeviceCommandData[psCommand->CommandType].pfnCmdProc((IMG_HANDLE)psCmdCompleteData,
+															   (IMG_UINT32)psCommand->uDataSize,
+															   psCommand->pvData) == IMG_FALSE)
+	{
+		/*
+			clean-up:
+			free cmd complete structure
+		*/
+		psCmdCompleteData->bInUse = IMG_FALSE;
+		eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+		PVR_LOG(("Failed to submit command from queue processor, this could cause sync wedge!"));
+	}
+	else
+	{
+		/* Increment the CCB offset */
+		psDeviceCommandData[psCommand->CommandType].ui32CCBOffset = (ui32CCBOffset + 1) % DC_NUM_COMMANDS_PER_TYPE;
+	}
+
+	return eError;
+}
+
+
+static IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	if (psDeviceNode->bReProcessDeviceCommandComplete &&
+		psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+	{
+		(*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVProcessQueues
+
+ @Description	Tries to process a command from each Q
+
+ @input ui32CallerID - used to distinguish between async ISR/DPC type calls
+ 						the synchronous services driver
+ @input	bFlush - flush commands with stale dependencies (only used for HW recovery)
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL	bFlush)
+{
+	PVRSRV_QUEUE_INFO 	*psQueue;
+	SYS_DATA			*psSysData;
+	PVRSRV_COMMAND 		*psCommand;
+/*	PVRSRV_DEVICE_NODE	*psDeviceNode;*/
+
+	SysAcquireData(&psSysData);
+
+	/* Ensure we don't corrupt queue list, by blocking access. This is required for OSs where
+	    multiple ISR threads may exist simultaneously (eg WinXP DPC routines)
+	*/
+	if (psSysData->psQueueList == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
+		return PVRSRV_OK;
+	}
+
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	while (OSLockResourceAndBlockMISR(&psSysData->sQProcessResource, ISR_ID) != PVRSRV_OK)
+#else /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	while (OSLockResource(&psSysData->sQProcessResource, ISR_ID) != PVRSRV_OK)
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	{
+		OSWaitus(1);
+	};
+	
+	psQueue = psSysData->psQueueList;
+
+	if(!psQueue)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
+	}
+
+	if (bFlush)
+	{
+		PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+	}
+
+	while (psQueue)
+	{
+		while (psQueue->uReadOffset != psQueue->uWriteOffset)
+		{
+			psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->uReadOffset);
+
+			if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
+			{
+				/* processed cmd so update queue */
+				UPDATE_QUEUE_ROFF(psQueue, psCommand->uCmdSize)
+				continue;
+			}
+
+			break;
+		}
+		psQueue = psQueue->psNextKM;
+	}
+
+	if (bFlush)
+	{
+		PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+	}
+
+	/* Re-process command complete handlers if necessary. */
+	List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+									&PVRSRVProcessQueues_ForEachCb);
+
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	OSUnlockResourceAndUnblockMISR(&psSysData->sQProcessResource, ISR_ID);
+#else /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+	OSUnlockResource(&psSysData->sQProcessResource, ISR_ID);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+
+	return PVRSRV_OK;
+}
+
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+extern void sgxfreq_notif_sgx_frame_done(void);
+#endif /* (SYS_OMAP4_HAS_DVFS_FRAMEWORK) */
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVCommandCompleteKM
+
+ @Description	Updates non-private command complete sync objects
+
+ @Input		hCmdCookie : command cookie
+ @Input		bScheduleMISR : boolean to schedule MISR
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE	hCmdCookie,
+								 IMG_BOOL	bScheduleMISR)
+{
+	IMG_UINT32				i;
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+	SYS_DATA				*psSysData;
+
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	sgxfreq_notif_sgx_frame_done();
+#endif /* (SYS_OMAP_HAS_DVFS_FRAMEWORK) */
+
+	SysAcquireData(&psSysData);
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_START,
+			QUEUE_TOKEN_COMMAND_COMPLETE);
+
+	/* update DST(s) syncs */
+	for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
+	{
+		psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+
+#if !((defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+		PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM, IMG_NULL);
+#endif
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_DST,
+					  psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM,
+					  PVRSRV_SYNCOP_COMPLETE);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+				i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
+				psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+	}
+
+	/* update SRC(s) syncs */
+	for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
+	{
+		psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete++;
+
+#if !((defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+		PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM, IMG_NULL);
+#endif
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_SRC,
+					  psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM,
+					  PVRSRV_SYNCOP_COMPLETE);
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+				i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+				psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
+				psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+	}
+
+#if (defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	if(psCmdCompleteData->ui32DstSyncCount || psCmdCompleteData->ui32SrcSyncCount)
+	{
+		/* Add work to worker thread for checking and freeing of kernel sync */
+		queue_work(gpsWorkQueue, &gsWork);
+	}
+#endif
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_END,
+			QUEUE_TOKEN_COMMAND_COMPLETE);
+
+	if (psCmdCompleteData->pfnCommandComplete)
+	{
+		psCmdCompleteData->pfnCommandComplete(psCmdCompleteData->hCallbackData);
+	}
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	if(psCmdCompleteData->pvTimeline)
+	{
+		sw_sync_timeline_inc(psCmdCompleteData->pvTimeline, 1);
+		sync_fence_put(psCmdCompleteData->pvCleanupFence);
+	}
+#elif defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	if(psCmdCompleteData->pvTimeline)
+	{
+		SyncSWTimelineAdvanceKM(psCmdCompleteData->pvTimeline);
+		SyncSWTimelineReleaseKM(psCmdCompleteData->pvTimeline);
+		psCmdCompleteData->pvTimeline = IMG_NULL;
+
+		psCmdCompleteData->pvCleanupFence = IMG_NULL;
+	}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+
+	/* free command complete storage */
+	psCmdCompleteData->bInUse = IMG_FALSE;
+
+	/* FIXME: This may cause unrelated devices to be woken up. */
+	PVRSRVScheduleDeviceCallbacks();
+
+	if(bScheduleMISR)
+	{
+		OSScheduleMISR(psSysData);
+	}
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRegisterCmdProcListKM
+
+ @Description
+
+ registers a list of private command processing functions with the Command
+ Queue Manager
+
+ @Input		ui32DevIndex : device index
+
+ @Input		 ppfnCmdProcList : function ptr table of private command processors
+
+ @Input		ui32MaxSyncsPerCmd : max number of syncobjects used by command
+
+ @Input		ui32CmdCount : number of entries in function ptr table
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32		ui32DevIndex,
+										 PFN_CMD_PROC	*ppfnCmdProcList,
+										 IMG_UINT32		ui32MaxSyncsPerCmd[][2],
+										 IMG_UINT32		ui32CmdCount)
+{
+	SYS_DATA				*psSysData;
+	PVRSRV_ERROR			eError;
+	IMG_UINT32				ui32CmdCounter, ui32CmdTypeCounter;
+	IMG_SIZE_T				ui32AllocSize;
+	DEVICE_COMMAND_DATA		*psDeviceCommandData;
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData;
+
+	/* validate device type */
+	if(ui32DevIndex >= SYS_DEVICE_COUNT)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+					"PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
+					ui32DevIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* acquire system data structure */
+	SysAcquireData(&psSysData);
+
+	/* array of pointers for each command store */
+	ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+						ui32AllocSize,
+						(IMG_VOID **)&psDeviceCommandData, IMG_NULL,
+						"Array of Pointers for Command Store");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+		goto ErrorExit;
+	}
+
+	psSysData->apsDeviceCommandData[ui32DevIndex] = psDeviceCommandData;
+
+	for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+	{
+		psDeviceCommandData[ui32CmdTypeCounter].pfnCmdProc = ppfnCmdProcList[ui32CmdTypeCounter];
+		psDeviceCommandData[ui32CmdTypeCounter].ui32CCBOffset = 0;
+		psDeviceCommandData[ui32CmdTypeCounter].ui32MaxDstSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0];
+		psDeviceCommandData[ui32CmdTypeCounter].ui32MaxSrcSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1];
+		for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+		{
+			/*
+				allocate storage for the sync update on command complete
+			*/
+			ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA) /* space for one GENERIC_CMD_COMPLETE */
+						  + ((ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]
+						  +	ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1])
+						  * sizeof(PVRSRV_SYNC_OBJECT));	 /* space for max sync objects */
+
+			eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+								ui32AllocSize,
+								(IMG_VOID **)&psCmdCompleteData,
+								IMG_NULL,
+								"Command Complete Data");
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d", ui32CmdTypeCounter));
+				goto ErrorExit;
+			}
+			
+			psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = psCmdCompleteData;
+			
+			/* clear memory */
+			OSMemSet(psCmdCompleteData, 0x00, ui32AllocSize);
+
+			/* setup sync pointers */
+			psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
+											(((IMG_UINTPTR_T)psCmdCompleteData)
+											+ sizeof(COMMAND_COMPLETE_DATA));
+			psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*)
+											(((IMG_UINTPTR_T)psCmdCompleteData->psDstSync)
+											+ (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]));
+
+			psCmdCompleteData->ui32AllocSize = (IMG_UINT32)ui32AllocSize;
+		}
+	}
+
+	return PVRSRV_OK;
+
+ErrorExit:
+
+	/* clean-up if things went wrong */
+	if (PVRSRVRemoveCmdProcListKM(ui32DevIndex, ui32CmdCount) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVRegisterCmdProcListKM: Failed to clean up after error, device 0x%x",
+				ui32DevIndex));
+	}
+	
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVRemoveCmdProcListKM
+
+ @Description
+
+ removes a list of private command processing functions and data from the
+ Queue Manager
+
+ @Input		ui32DevIndex : device index
+
+ @Input		ui32CmdCount : number of entries in function ptr table
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+									   IMG_UINT32 ui32CmdCount)
+{
+	SYS_DATA				*psSysData;
+	IMG_UINT32				ui32CmdTypeCounter, ui32CmdCounter;
+	DEVICE_COMMAND_DATA		*psDeviceCommandData;
+	COMMAND_COMPLETE_DATA	*psCmdCompleteData;
+	IMG_SIZE_T				ui32AllocSize;
+
+	/* validate device type */
+	if(ui32DevIndex >= SYS_DEVICE_COUNT)
+	{
+		PVR_DPF((PVR_DBG_ERROR,
+				"PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+				ui32DevIndex));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* acquire system data structure */
+	SysAcquireData(&psSysData);
+
+	psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+	if(psDeviceCommandData != IMG_NULL)
+	{
+		for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+		{
+			for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+			{
+				psCmdCompleteData = psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter];
+				
+				/* free the cmd complete structure array entries */
+				if (psCmdCompleteData != IMG_NULL)
+				{
+					PVR_ASSERT(psCmdCompleteData->bInUse == IMG_FALSE);
+					OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, psCmdCompleteData->ui32AllocSize,
+							  psCmdCompleteData, IMG_NULL);
+					psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = IMG_NULL;
+				}
+			}
+		}
+
+		/* free the cmd complete structure array for the device */
+		ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psDeviceCommandData, IMG_NULL);
+		psSysData->apsDeviceCommandData[ui32DevIndex] = IMG_NULL;
+	}
+
+	return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (queue.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/ra.c b/drivers/gpu/pvr/services4/srvkm/common/ra.c
new file mode 100644
index 0000000..9816a9a
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/ra.c
@@ -0,0 +1,2217 @@
+/*************************************************************************/ /*!
+@Title          Resource Allocator
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description
+  Implements generic resource allocation. The resource
+  allocator was originally intended to manage address spaces in
+  practice the resource allocator is generic and can manages arbitrary
+  sets of integers.
+ 
+  Resources are allocated from arenas. Arena's can be created with an
+  initial span of resources. Further resources spans can be added to
+  arenas. A call back mechanism allows an arena to request further
+  resource spans on demand.
+ 
+  Each arena maintains an ordered list of resource segments each
+  described by a boundary tag. Each boundary tag describes a segment
+  of resources which are either 'free', available for allocation, or
+  'busy' currently allocated. Adjacent 'free' segments are always
+  coallesced to avoid fragmentation.
+ 
+  For allocation, all 'free' segments are kept on lists of 'free'
+  segments in a table index by pvr_log2(segment size). ie Each table index
+  n holds 'free' segments in the size range 2**(n-1) -> 2**n.
+ 
+  Allocation policy is based on an *almost* best fit
+  stratedy. Choosing any segment from the appropriate table entry
+  guarantees that we choose a segment which is with a power of 2 of
+  the size we are allocating.
+ 
+  Allocated segments are inserted into a self scaling hash table which
+  maps the base resource of the span to the relevant boundary
+  tag. This allows the code to get back to the bounary tag without
+  exporting explicit boundary tag references through the API.
+ 
+  Each arena has an associated quantum size, all allocations from the
+  arena are made in multiples of the basic quantum.
+ 
+  On resource exhaustion in an arena, a callback if provided will be
+  used to request further resources. Resouces spans allocated by the
+  callback mechanism are delimited by special boundary tag markers of
+  zero span, 'span' markers. Span markers are never coallesced. Span
+  markers are used to detect when an imported span is completely free
+  and can be deallocated by the callback mechanism.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* Issues:
+ * - flags, flags are passed into the resource allocator but are not currently used.
+ * - determination, of import size, is currently braindead.
+ * - debug code should be moved out to own module and #ifdef'd
+ */
+
+#include "services_headers.h"
+#include "hash.h"
+#include "ra.h"
+#include "buffer_manager.h"
+#include "osfunc.h"
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/kernel.h>
+#include "proc.h"
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+#include <stdio.h>
+#endif
+
+/* The initial, and minimum size of the live address -> boundary tag
+   structure hash table. The value 64 is a fairly arbitrary
+   choice. The hash table resizes on demand so the value choosen is
+   not critical. */
+#define MINIMUM_HASH_SIZE (64)
+
+#if defined(VALIDATE_ARENA_TEST)
+
+/* This test validates the doubly linked ordered list of boundary tags, by
+checking that adjacent members of the list have compatible eResourceSpan
+and eResourceType values. */
+
+typedef enum RESOURCE_DESCRIPTOR_TAG {
+
+	RESOURCE_SPAN_LIVE				= 10,
+	RESOURCE_SPAN_FREE,
+	IMPORTED_RESOURCE_SPAN_START,
+	IMPORTED_RESOURCE_SPAN_LIVE,
+	IMPORTED_RESOURCE_SPAN_FREE,
+	IMPORTED_RESOURCE_SPAN_END,
+
+} RESOURCE_DESCRIPTOR;
+
+typedef enum RESOURCE_TYPE_TAG {
+
+	IMPORTED_RESOURCE_TYPE		= 20,
+	NON_IMPORTED_RESOURCE_TYPE
+
+} RESOURCE_TYPE;
+
+
+static IMG_UINT32 ui32BoundaryTagID = 0;
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena);
+#endif
+
+/* boundary tags, used to describe a resource segment */
+struct _BT_
+{
+	enum bt_type
+	{
+		btt_span,				/* span markers */
+		btt_free,				/* free resource segment */
+		btt_live				/* allocated resource segment */
+	} type;
+
+	/* The base resource and extent of this segment */
+	IMG_UINTPTR_T base;
+	IMG_SIZE_T uSize;
+
+	/* doubly linked ordered list of all segments within the arena */
+	struct _BT_ *pNextSegment;
+	struct _BT_ *pPrevSegment;
+	/* doubly linked un-ordered list of free segments. */
+	struct _BT_ *pNextFree;
+	struct _BT_ *pPrevFree;
+	/* a user reference associated with this span, user references are
+	 * currently only provided in the callback mechanism */
+	BM_MAPPING *psMapping;
+
+#if defined(VALIDATE_ARENA_TEST)
+	RESOURCE_DESCRIPTOR eResourceSpan;
+	RESOURCE_TYPE		eResourceType;
+
+	/* This variable provides a reference (used in debug messages) to incompatible
+	boundary tags within the doubly linked ordered list. */
+	IMG_UINT32			ui32BoundaryTagID;
+#endif
+
+};
+typedef struct _BT_ BT;
+
+
+/* resource allocation arena */
+struct _RA_ARENA_
+{
+	/* arena name for diagnostics output */
+	IMG_CHAR *name;
+
+	/* allocations within this arena are quantum sized */
+	IMG_SIZE_T uQuantum;
+
+	/* import interface, if provided */
+	IMG_BOOL (*pImportAlloc)(IMG_VOID *,
+							 IMG_SIZE_T uSize,
+							 IMG_SIZE_T *pActualSize,
+							 BM_MAPPING **ppsMapping,
+							 IMG_UINT32 uFlags,
+							 IMG_PVOID pvPrivData,
+							 IMG_UINT32 ui32PrivDataLength,
+							 IMG_UINTPTR_T *pBase);
+	IMG_VOID (*pImportFree) (IMG_VOID *,
+						 IMG_UINTPTR_T,
+						 BM_MAPPING *psMapping);
+	IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
+
+	/* arbitrary handle provided by arena owner to be passed into the
+	 * import alloc and free hooks */
+	IMG_VOID *pImportHandle;
+
+	/* head of list of free boundary tags for indexed by pvr_log2 of the
+	   boundary tag size */
+#define FREE_TABLE_LIMIT 32
+
+	/* power-of-two table of free lists */
+	BT *aHeadFree [FREE_TABLE_LIMIT];
+
+	/* resource ordered segment list */
+	BT *pHeadSegment;
+	BT *pTailSegment;
+
+	/* segment address to boundary tag hash table */
+	HASH_TABLE *pSegmentHash;
+
+#ifdef RA_STATS
+	RA_STATISTICS sStatistics;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+#define PROC_NAME_SIZE		64
+
+	struct pvr_proc_dir_entry* pProcInfo;
+	struct pvr_proc_dir_entry* pProcSegs;
+
+	IMG_BOOL bInitProcEntry;
+#endif
+};
+/* #define ENABLE_RA_DUMP	1 */
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID RA_Dump (RA_ARENA *pArena);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
+
+#ifdef USE_BM_FREESPACE_CHECK
+IMG_VOID CheckBMFreespace(IMG_VOID);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
+{
+	IMG_CHAR *pT;
+
+	for(pT = pS; *pT != 0; pT++)
+	{
+		if (*pT == ' ' || *pT == '\t')
+		{
+			*pT = '_';
+		}
+	}
+
+	return pS;
+}
+#endif
+
+/*!
+******************************************************************************
+	@Function       _RequestAllocFail
+
+	@Description    Default callback allocator used if no callback is
+                    specified, always fails to allocate further resources to the
+                    arena.
+
+	@Input          _h - callback handle
+	@Input          _uSize - requested allocation size
+	@Output         _pActualSize - actual allocation size
+	@Input          _pRef - user reference
+	@Input          _uflags - allocation flags
+	@Input          _pvPrivData - private data
+	@Input          _ui32PrivDataLength - private data length
+	@Input          _pBase - receives allocated base
+
+	@Return         IMG_FALSE, this function always fails to allocate.
+******************************************************************************/
+static IMG_BOOL
+_RequestAllocFail (IMG_VOID *_h,
+				  IMG_SIZE_T _uSize,
+				  IMG_SIZE_T *_pActualSize,
+				  BM_MAPPING **_ppsMapping,
+				  IMG_UINT32 _uFlags,
+				  IMG_PVOID _pvPrivData,
+				  IMG_UINT32 _ui32PrivDataLength,
+				  IMG_UINTPTR_T *_pBase)
+{
+	PVR_UNREFERENCED_PARAMETER (_h);
+	PVR_UNREFERENCED_PARAMETER (_uSize);
+	PVR_UNREFERENCED_PARAMETER (_pActualSize);
+	PVR_UNREFERENCED_PARAMETER (_ppsMapping);
+	PVR_UNREFERENCED_PARAMETER (_uFlags);
+	PVR_UNREFERENCED_PARAMETER (_pBase);
+	PVR_UNREFERENCED_PARAMETER (_pvPrivData);
+	PVR_UNREFERENCED_PARAMETER (_ui32PrivDataLength);
+
+	return IMG_FALSE;
+}
+
+/*!
+******************************************************************************
+	@Function       pvr_log2
+
+	@Description    Computes the floor of the log base 2 of a unsigned integer
+
+	@Input          n - unsigned integer
+
+	@Return         Floor(Log2(n))
+******************************************************************************/
+static IMG_UINT32
+pvr_log2 (IMG_SIZE_T n)
+{
+	IMG_UINT32 l = 0;
+	n>>=1;
+	while (n>0)
+	{
+		n>>=1;
+		l++;
+	}
+	return l;
+}
+
+/*!
+******************************************************************************
+	@Function       _SegmentListInsertAfter
+
+	@Description    Insert a boundary tag into an arena segment list after a
+                    specified boundary tag.
+
+	@Input          pArena - the arena.
+	@Input          pInsertionPoint - the insertion point.
+	@Input          pBT - the boundary tag to insert.
+
+	@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+_SegmentListInsertAfter (RA_ARENA *pArena,
+						 BT *pInsertionPoint,
+						 BT *pBT)
+{
+	PVR_ASSERT (pArena != IMG_NULL);
+	PVR_ASSERT (pInsertionPoint != IMG_NULL);
+
+	if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL))
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	pBT->pNextSegment = pInsertionPoint->pNextSegment;
+	pBT->pPrevSegment = pInsertionPoint;
+	if (pInsertionPoint->pNextSegment == IMG_NULL)
+		pArena->pTailSegment = pBT;
+	else
+		pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+	pInsertionPoint->pNextSegment = pBT;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+	@Function       _SegmentListInsert
+
+	@Description    Insert a boundary tag into an arena segment list at the
+                    appropriate point.
+
+	@Input          pArena - the arena.
+	@Input          pBT - the boundary tag to insert.
+
+	@Return         None
+******************************************************************************/
+static PVRSRV_ERROR
+_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	/* insert into the segment chain */
+	if (pArena->pHeadSegment == IMG_NULL)
+	{
+		pArena->pHeadSegment = pArena->pTailSegment = pBT;
+		pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
+	}
+	else
+	{
+		BT *pBTScan;
+
+		if (pBT->base < pArena->pHeadSegment->base)
+		{
+			/* The base address of pBT is less than the base address of the boundary tag
+			at the head of the list - so insert this boundary tag at the head. */
+			pBT->pNextSegment = pArena->pHeadSegment;
+			pArena->pHeadSegment->pPrevSegment = pBT;
+			pArena->pHeadSegment = pBT;
+			pBT->pPrevSegment = IMG_NULL;
+		}
+		else
+		{
+
+			/* The base address of pBT is greater than or equal to that of the boundary tag
+			at the head of the list. Search for the insertion point: pBT must be inserted
+			before the first boundary tag with a greater base value - or at the end of the list.
+			*/
+			pBTScan = pArena->pHeadSegment;
+
+			while ((pBTScan->pNextSegment != IMG_NULL)  && (pBT->base >= pBTScan->pNextSegment->base))
+			{
+				pBTScan = pBTScan->pNextSegment;
+			}
+
+			eError = _SegmentListInsertAfter (pArena, pBTScan, pBT);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+	}
+	return eError;
+}
+
+/*!
+******************************************************************************
+	@Function       _SegmentListRemove
+
+	@Description    Remove a boundary tag from an arena segment list.
+
+	@Input          pArena - the arena.
+	@Input          pBT - the boundary tag to remove.
+
+	@Return         None
+******************************************************************************/
+static IMG_VOID
+_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
+{
+	if (pBT->pPrevSegment == IMG_NULL)
+		pArena->pHeadSegment = pBT->pNextSegment;
+	else
+		pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+	if (pBT->pNextSegment == IMG_NULL)
+		pArena->pTailSegment = pBT->pPrevSegment;
+	else
+		pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+/*!
+******************************************************************************
+	@Function       _SegmentSplit
+
+	@Description    Split a segment into two, maintain the arena segment list. The
+                    boundary tag should not be in the free table. Neither the
+                    original or the new neighbour bounary tag will be in the free
+                    table.
+
+	@Input          pArena - the arena.
+	@Input          pBT - the boundary tag to split.
+	@Input          uSize - the required segment size of boundary tag after
+	           	     splitting.
+
+	@Return         New neighbour boundary tag.
+
+******************************************************************************/
+static BT *
+_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
+{
+	BT *pNeighbour;
+
+	PVR_ASSERT (pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena"));
+		return IMG_NULL;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(BT),
+					(IMG_VOID **)&pNeighbour, IMG_NULL,
+					"Boundary Tag") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	OSMemSet(pNeighbour, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+	pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+	pNeighbour->pPrevSegment = pBT;
+	pNeighbour->pNextSegment = pBT->pNextSegment;
+	if (pBT->pNextSegment == IMG_NULL)
+		pArena->pTailSegment = pNeighbour;
+	else
+		pBT->pNextSegment->pPrevSegment = pNeighbour;
+	pBT->pNextSegment = pNeighbour;
+
+	pNeighbour->type = btt_free;
+	pNeighbour->uSize = pBT->uSize - uSize;
+	pNeighbour->base = pBT->base + uSize;
+	pNeighbour->psMapping = pBT->psMapping;
+	pBT->uSize = uSize;
+
+#if defined(VALIDATE_ARENA_TEST)
+	if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+	{
+		pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
+		pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+	}
+	else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+	{
+		pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+		pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
+		PVR_DBG_BREAK;
+	}
+#endif
+
+	return pNeighbour;
+}
+
+/*!
+******************************************************************************
+	@Function       _FreeListInsert
+
+	@Description    Insert a boundary tag into an arena free table.
+
+	@Input          pArena - the arena.
+	@Input          pBT - the boundary tag.
+
+	@Return         None
+
+******************************************************************************/
+static IMG_VOID
+_FreeListInsert (RA_ARENA *pArena, BT *pBT)
+{
+	IMG_UINT32 uIndex;
+	uIndex = pvr_log2 (pBT->uSize);
+	pBT->type = btt_free;
+	pBT->pNextFree = pArena->aHeadFree [uIndex];
+	pBT->pPrevFree = IMG_NULL;
+	if (pArena->aHeadFree[uIndex] != IMG_NULL)
+		pArena->aHeadFree[uIndex]->pPrevFree = pBT;
+	pArena->aHeadFree [uIndex] = pBT;
+}
+
+/*!
+******************************************************************************
+	@Function       _FreeListRemove
+
+	@Description    Remove a boundary tag from an arena free table.
+
+	@Input          pArena - the arena.
+	@Input          pBT - the boundary tag.
+
+	@Return         None
+
+******************************************************************************/
+static IMG_VOID
+_FreeListRemove (RA_ARENA *pArena, BT *pBT)
+{
+	IMG_UINT32 uIndex;
+	uIndex = pvr_log2 (pBT->uSize);
+	if (pBT->pNextFree != IMG_NULL)
+		pBT->pNextFree->pPrevFree = pBT->pPrevFree;
+	if (pBT->pPrevFree == IMG_NULL)
+		pArena->aHeadFree[uIndex] = pBT->pNextFree;
+	else
+		pBT->pPrevFree->pNextFree = pBT->pNextFree;
+}
+
+/*!
+******************************************************************************
+	@Function       _BuildSpanMarker
+
+	@Description    Construct a span marker boundary tag.
+
+	@Input          pArena - arena to contain span marker
+	@Input          base - the base of the bounary tag.
+
+	@Return         span marker boundary tag
+
+******************************************************************************/
+static BT *
+_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	BT *pBT;
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(BT),
+					(IMG_VOID **)&pBT, IMG_NULL,
+					"Boundary Tag") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+	pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+	pBT->type = btt_span;
+	pBT->base = base;
+	pBT->uSize = uSize;
+	pBT->psMapping = IMG_NULL;
+
+	return pBT;
+}
+
+/*!
+******************************************************************************
+	@Function       _BuildBT
+
+	@Description    Construct a boundary tag for a free segment.
+
+	@Input          base - the base of the resource segment.
+	@Input          uSize - the extent of the resouce segment.
+
+	@Return         boundary tag
+
+******************************************************************************/
+static BT *
+_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	BT *pBT;
+
+	if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					sizeof(BT),
+					(IMG_VOID **)&pBT, IMG_NULL,
+					"Boundary Tag") != PVRSRV_OK)
+	{
+		return IMG_NULL;
+	}
+
+	OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+	pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+	pBT->type = btt_free;
+	pBT->base = base;
+	pBT->uSize = uSize;
+
+	return pBT;
+}
+
+/*!
+******************************************************************************
+	@Function       _InsertResource
+
+	@Description    Add a free resource segment to an arena.
+
+	@Input          pArena - the arena.
+	@Input          base - the base of the resource segment.
+	@Input          uSize - the extent of the resource segment.
+
+	@Return         New bucket pointer
+                    IMG_NULL failure
+
+******************************************************************************/
+static BT *
+_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	BT *pBT;
+	PVR_ASSERT (pArena!=IMG_NULL);
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena"));
+		return IMG_NULL;
+	}
+
+	pBT = _BuildBT (base, uSize);
+	if (pBT != IMG_NULL)
+	{
+
+#if defined(VALIDATE_ARENA_TEST)
+		pBT->eResourceSpan = RESOURCE_SPAN_FREE;
+		pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+#endif
+
+		if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK)
+		{
+			PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed"));
+			return IMG_NULL;
+		}
+		_FreeListInsert (pArena, pBT);
+#ifdef RA_STATS
+		pArena->sStatistics.uTotalResourceCount+=uSize;
+		pArena->sStatistics.uFreeResourceCount+=uSize;
+		pArena->sStatistics.uSpanCount++;
+#endif
+	}
+	return pBT;
+}
+
+/*!
+******************************************************************************
+	@Function       _InsertResourceSpan
+
+	@Description    Add a free resource span to an arena, complete with span markers.
+
+	@Input          pArena - the arena.
+	@Input          base - the base of the resource segment.
+	@Input          uSize - the extent of the resource segment.
+
+	@Return         the boundary tag representing the free resource segment,
+                    or IMG_NULL on failure.
+******************************************************************************/
+static BT *
+_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	PVRSRV_ERROR eError;
+	BT *pSpanStart;
+	BT *pSpanEnd;
+	BT *pBT;
+
+	PVR_ASSERT (pArena != IMG_NULL);
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena"));
+		return IMG_NULL;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_InsertResourceSpan: arena='%s', base=0x" UINTPTR_FMT ", size=0x%" SIZE_T_FMT_LEN "x",
+			  pArena->name, base, uSize));
+
+	pSpanStart = _BuildSpanMarker (base, uSize);
+	if (pSpanStart == IMG_NULL)
+	{
+		goto fail_start;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
+	pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+	pSpanEnd = _BuildSpanMarker (base + uSize, 0);
+	if (pSpanEnd == IMG_NULL)
+	{
+		goto fail_end;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
+	pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+	pBT = _BuildBT (base, uSize);
+	if (pBT == IMG_NULL)
+	{
+		goto fail_bt;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+	pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+	eError = _SegmentListInsert (pArena, pSpanStart);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_SegListInsert;
+	}
+
+	eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_SegListInsert;
+	}
+
+	_FreeListInsert (pArena, pBT);
+
+	eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd);
+	if (eError != PVRSRV_OK)
+	{
+		goto fail_SegListInsert;
+	}
+
+#ifdef RA_STATS
+	pArena->sStatistics.uTotalResourceCount+=uSize;
+/*	pArena->sStatistics.uFreeResourceCount+=uSize;
+	This has got to be wrong as uFreeResourceCount ends
+	up larger than uTotalResourceCount by uTotalResourceCount
+	- allocated memory
+*/
+#endif
+	return pBT;
+
+  fail_SegListInsert:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+  fail_bt:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+  fail_end:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+  fail_start:
+	return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+	@Function       _FreeBT
+
+	@Description    Free a boundary tag taking care of the segment list and the
+                    boundary tag free table.
+
+	@Input          pArena - the arena.
+	@Input          pBT - the boundary tag to free.
+	@Input          bFreeBackingStore - Should backing for the memory be freed
+										 as well.
+	@Return         None
+******************************************************************************/
+static IMG_VOID
+_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
+{
+	BT *pNeighbour;
+	IMG_UINTPTR_T uOrigBase;
+	IMG_SIZE_T uOrigSize;
+
+	PVR_ASSERT (pArena!=IMG_NULL);
+	PVR_ASSERT (pBT!=IMG_NULL);
+
+	if ((pArena == IMG_NULL) || (pBT == IMG_NULL))
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter"));
+		return;
+	}
+
+#ifdef RA_STATS
+	pArena->sStatistics.uLiveSegmentCount--;
+	pArena->sStatistics.uFreeSegmentCount++;
+	pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+#endif
+
+	uOrigBase = pBT->base;
+	uOrigSize = pBT->uSize;
+
+	/* try and coalesce with left neighbour */
+	pNeighbour = pBT->pPrevSegment;
+	if (pNeighbour!=IMG_NULL
+		&& pNeighbour->type == btt_free
+		&& pNeighbour->base + pNeighbour->uSize == pBT->base)
+	{
+		_FreeListRemove (pArena, pNeighbour);
+		_SegmentListRemove (pArena, pNeighbour);
+		pBT->base = pNeighbour->base;
+		pBT->uSize += pNeighbour->uSize;
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+		/*not nulling original pointer, already overwritten*/
+#ifdef RA_STATS
+		pArena->sStatistics.uFreeSegmentCount--;
+#endif
+	}
+
+	/* try to coalesce with right neighbour */
+	pNeighbour = pBT->pNextSegment;
+	if (pNeighbour!=IMG_NULL
+		&& pNeighbour->type == btt_free
+		&& pBT->base + pBT->uSize == pNeighbour->base)
+	{
+		_FreeListRemove (pArena, pNeighbour);
+		_SegmentListRemove (pArena, pNeighbour);
+		pBT->uSize += pNeighbour->uSize;
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+		/*not nulling original pointer, already overwritten*/
+#ifdef RA_STATS
+		pArena->sStatistics.uFreeSegmentCount--;
+#endif
+	}
+
+	/* try to free backing store memory. */
+	if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
+	{
+		IMG_UINTPTR_T	uRoundedStart, uRoundedEnd;
+
+		/* Work out the first address we might be able to free. */
+		uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
+		/* If a span is still using that address then leave it. */
+		if (uRoundedStart < pBT->base)
+		{
+			uRoundedStart += pArena->uQuantum;
+		}
+
+		/* Work out the last address we might be able to free. */
+		uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
+		/* If a span is still using that addres then leave it. */
+		if (uRoundedEnd > (pBT->base + pBT->uSize))
+		{
+			uRoundedEnd -= pArena->uQuantum;
+		}
+
+		if (uRoundedStart < uRoundedEnd)
+		{
+			pArena->pBackingStoreFree(pArena->pImportHandle, (IMG_SIZE_T)uRoundedStart, (IMG_SIZE_T)uRoundedEnd, (IMG_HANDLE)0);
+		}
+	}
+
+	if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
+		&& pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
+	{
+		BT *next = pBT->pNextSegment;
+		BT *prev = pBT->pPrevSegment;
+		_SegmentListRemove (pArena, next);
+		_SegmentListRemove (pArena, prev);
+		_SegmentListRemove (pArena, pBT);
+		pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping);
+#ifdef RA_STATS
+		pArena->sStatistics.uSpanCount--;
+		pArena->sStatistics.uExportCount++;
+		pArena->sStatistics.uFreeSegmentCount--;
+		pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+		pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
+#endif
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
+		/*not nulling original pointer, already overwritten*/
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
+		/*not nulling original pointer, already overwritten*/
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+	}
+	else
+		_FreeListInsert (pArena, pBT);
+}
+
+
+/*!
+******************************************************************************
+	@Function       _AttemptAllocAligned
+
+	@Description    Attempt an allocation from an arena.
+
+	@Input          pArena - the arena.
+	@Input          uSize - the requested allocation size.
+	@Output         ppsMapping - the user references associated with
+	                 the allocated segment.
+	@Input          flags - allocation flags
+	@Input          uAlignment - required uAlignment, or 0
+	@Input          uAlignmentOffset
+	@Output         base - allocated resource base
+
+	@Return         IMG_FALSE failure
+                    IMG_TRUE success
+******************************************************************************/
+static IMG_BOOL
+_AttemptAllocAligned (RA_ARENA *pArena,
+					  IMG_SIZE_T uSize,
+					  BM_MAPPING **ppsMapping,
+					  IMG_UINT32 uFlags,
+					  IMG_UINT32 uAlignment,
+					  IMG_UINT32 uAlignmentOffset,
+					  IMG_UINTPTR_T *base)
+{
+	IMG_UINT32 uIndex;
+	PVR_ASSERT (pArena!=IMG_NULL);
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena"));
+		return IMG_FALSE;
+	}
+
+	if (uAlignment>1)
+		uAlignmentOffset %= uAlignment;
+
+	/* search for a near fit free boundary tag, start looking at the
+	   pvr_log2 free table for our required size and work on up the
+	   table. */
+	uIndex = pvr_log2 (uSize);
+
+	while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
+		uIndex++;
+
+	while (uIndex < FREE_TABLE_LIMIT)
+	{
+		if (pArena->aHeadFree[uIndex]!=IMG_NULL)
+		{
+			/* we have a cached free boundary tag */
+			BT *pBT;
+
+			pBT = pArena->aHeadFree [uIndex];
+			while (pBT!=IMG_NULL)
+			{
+				IMG_UINTPTR_T aligned_base;
+
+				if (uAlignment>1)
+					aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
+				else
+					aligned_base = pBT->base;
+				PVR_DPF ((PVR_DBG_MESSAGE,
+						  "RA_AttemptAllocAligned: pBT-base=0x" UINTPTR_FMT " "
+						  "pBT-size=0x%" SIZE_T_FMT_LEN "x alignedbase=0x" 
+						  UINTPTR_FMT " size=0x%" SIZE_T_FMT_LEN "x",
+						pBT->base, 
+                        pBT->uSize, 
+                        aligned_base, 
+                        uSize));
+
+				if (pBT->base + pBT->uSize >= aligned_base + uSize)
+				{
+					if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags)
+					{
+						_FreeListRemove (pArena, pBT);
+
+						PVR_ASSERT (pBT->type == btt_free);
+
+#ifdef RA_STATS
+						pArena->sStatistics.uLiveSegmentCount++;
+						pArena->sStatistics.uFreeSegmentCount--;
+						pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+#endif
+
+						/* with uAlignment we might need to discard the front of this segment */
+						if (aligned_base > pBT->base)
+						{
+							BT *pNeighbour;
+							pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base));
+							/* partition the buffer, create a new boundary tag */
+							if (pNeighbour==IMG_NULL)
+							{
+								PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
+								/* Put pBT back in the list */
+								_FreeListInsert (pArena, pBT);
+								return IMG_FALSE;
+							}
+
+							_FreeListInsert (pArena, pBT);
+	#ifdef RA_STATS
+							pArena->sStatistics.uFreeSegmentCount++;
+							pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+	#endif
+							pBT = pNeighbour;
+						}
+
+						/* the segment might be too big, if so, discard the back of the segment */
+						if (pBT->uSize > uSize)
+						{
+							BT *pNeighbour;
+							pNeighbour = _SegmentSplit (pArena, pBT, uSize);
+							/* partition the buffer, create a new boundary tag */
+							if (pNeighbour==IMG_NULL)
+							{
+								PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
+								/* Put pBT back in the list */
+								_FreeListInsert (pArena, pBT);
+								return IMG_FALSE;
+							}
+
+							_FreeListInsert (pArena, pNeighbour);
+	#ifdef RA_STATS
+							pArena->sStatistics.uFreeSegmentCount++;
+							pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
+	#endif
+						}
+
+						pBT->type = btt_live;
+
+#if defined(VALIDATE_ARENA_TEST)
+						if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE)
+						{
+							pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE;
+						}
+						else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+						{
+							pBT->eResourceSpan = RESOURCE_SPAN_LIVE;
+						}
+						else
+						{
+							PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized"));
+							PVR_DBG_BREAK;
+						}
+#endif
+						if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
+						{
+							_FreeBT (pArena, pBT, IMG_FALSE);
+							return IMG_FALSE;
+						}
+
+						if (ppsMapping!=IMG_NULL)
+							*ppsMapping = pBT->psMapping;
+
+						*base = pBT->base;
+
+						return IMG_TRUE;
+					}
+					else
+					{
+						PVR_DPF ((PVR_DBG_MESSAGE,
+								"AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags));
+
+					}
+				}
+				pBT = pBT->pNextFree;
+			}
+
+		}
+		uIndex++;
+	}
+
+	return IMG_FALSE;
+}
+
+
+
+/*!
+******************************************************************************
+	@Function       RA_Create
+
+	@Description    To create a resource arena.
+
+	@Input          name - the name of the arena for diagnostic purposes.
+	@Input          base - the base of an initial resource span or 0.
+	@Input          uSize - the size of an initial resource span or 0.
+	@Input          uQuantum - the arena allocation quantum.
+	@Input          alloc - a resource allocation callback or 0.
+	@Input          free - a resource de-allocation callback or 0.
+	@Input          backingstore_free - a callback to free resources for spans or 0.
+	@Input          pImportHandle - handle passed to alloc and free or 0.
+
+	@Return         arena handle, or IMG_NULL.
+******************************************************************************/
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+		   IMG_UINTPTR_T base,
+		   IMG_SIZE_T uSize,
+		   BM_MAPPING *psMapping,
+		   IMG_SIZE_T uQuantum,
+		   IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
+								 BM_MAPPING **ppsMapping, IMG_UINT32 _flags,
+								 IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength,
+								 IMG_UINTPTR_T *pBase),
+		   IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
+		   IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
+		   IMG_VOID *pImportHandle)
+{
+	RA_ARENA *pArena;
+	BT *pBT;
+	IMG_INT i;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Create: name='%s', base=0x" UINTPTR_FMT ", uSize=0x%" SIZE_T_FMT_LEN "x, alloc=0x%p, free=0x%p",
+			  name, base, uSize, imp_alloc, imp_free));
+
+
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof (*pArena),
+					 (IMG_VOID **)&pArena, IMG_NULL,
+					 "Resource Arena") != PVRSRV_OK)
+	{
+		goto arena_fail;
+	}
+
+	pArena->name = name;
+	pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail;
+	pArena->pImportFree = imp_free;
+	pArena->pBackingStoreFree = backingstore_free;
+	pArena->pImportHandle = pImportHandle;
+	for (i=0; i<FREE_TABLE_LIMIT; i++)
+		pArena->aHeadFree[i] = IMG_NULL;
+	pArena->pHeadSegment = IMG_NULL;
+	pArena->pTailSegment = IMG_NULL;
+	pArena->uQuantum = uQuantum;
+
+#ifdef RA_STATS
+	pArena->sStatistics.uSpanCount = 0;
+	pArena->sStatistics.uLiveSegmentCount = 0;
+	pArena->sStatistics.uFreeSegmentCount = 0;
+	pArena->sStatistics.uFreeResourceCount = 0;
+	pArena->sStatistics.uTotalResourceCount = 0;
+	pArena->sStatistics.uCumulativeAllocs = 0;
+	pArena->sStatistics.uCumulativeFrees = 0;
+	pArena->sStatistics.uImportCount = 0;
+	pArena->sStatistics.uExportCount = 0;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+	if(strcmp(pArena->name,"") != 0)
+	{
+		IMG_INT ret;
+		IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+		IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+		struct pvr_proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *,
+										 IMG_VOID*,
+										 pvr_next_proc_seq_t,
+										 pvr_show_proc_seq_t,
+										 pvr_off2element_proc_seq_t,
+										 pvr_startstop_proc_seq_t,
+										 pvr_proc_write_t);
+
+		pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+		/* Don't put shared heap info into a per process /proc subdirectory */
+		pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
+
+		ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
+		if (ret > 0 && ret < sizeof(szProcInfoName))
+		{
+			pArena->pProcInfo =  pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL,
+											 RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL);
+		}
+		else
+		{
+			pArena->pProcInfo = 0;
+			PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+		}
+
+		ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name);
+		if (ret > 0 && ret < sizeof(szProcInfoName))
+		{
+			pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
+											 RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL);
+		}
+		else
+		{
+			pArena->pProcSegs = 0;
+			PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+		}
+	}
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
+
+	pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
+	if (pArena->pSegmentHash==IMG_NULL)
+	{
+		goto hash_fail;
+	}
+	if (uSize>0)
+	{
+		uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
+		pBT = _InsertResource (pArena, base, uSize);
+		if (pBT == IMG_NULL)
+		{
+			goto insert_fail;
+		}
+		pBT->psMapping = psMapping;
+
+	}
+	return pArena;
+
+insert_fail:
+	HASH_Delete (pArena->pSegmentHash);
+hash_fail:
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+arena_fail:
+	return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+	@Function       RA_Delete
+
+	@Description    To delete a resource arena. All resources allocated from
+                    the arena must be freed before deleting the arena.
+
+	@Input          pArena - the arena to delete.
+
+	@Return         None
+******************************************************************************/
+IMG_VOID
+RA_Delete (RA_ARENA *pArena)
+{
+	IMG_UINT32 uIndex;
+
+	PVR_ASSERT(pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
+		return;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Delete: name='%s'", pArena->name));
+
+	for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
+		pArena->aHeadFree[uIndex] = IMG_NULL;
+
+	while (pArena->pHeadSegment != IMG_NULL)
+	{
+		BT *pBT = pArena->pHeadSegment;
+
+		if (pBT->type != btt_free)
+		{
+			PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: allocations still exist in the arena that is being destroyed"));
+			PVR_DPF ((PVR_DBG_ERROR,"Likely Cause: client drivers not freeing allocations before destroying devmemcontext"));
+			PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: base = 0x" UINTPTR_FMT " size=0x%" SIZE_T_FMT_LEN "x", pBT->base, pBT->uSize));
+		}
+
+		_SegmentListRemove (pArena, pBT);
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+		/*not nulling original pointer, it has changed*/
+#ifdef RA_STATS
+		pArena->sStatistics.uSpanCount--;
+#endif
+	}
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+	{
+		IMG_VOID (*pfnRemoveProcEntrySeq)(struct pvr_proc_dir_entry*);
+
+		pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq;
+
+		if (pArena->pProcInfo != 0)
+		{
+			pfnRemoveProcEntrySeq( pArena->pProcInfo );
+		}
+
+		if (pArena->pProcSegs != 0)
+		{
+			pfnRemoveProcEntrySeq( pArena->pProcSegs );
+		}
+	}
+#endif
+	HASH_Delete (pArena->pSegmentHash);
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+}
+
+/*!
+******************************************************************************
+	@Function       RA_TestDelete
+
+	@Description    To test whether it is safe to delete a resource arena. If any
+                    allocations have not been freed, the RA must not be deleted.
+
+	@Input          pArena - the arena to test.
+
+	@Return         IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete.
+******************************************************************************/
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena)
+{
+	PVR_ASSERT(pArena != IMG_NULL);
+
+	if (pArena != IMG_NULL)
+	{
+		while (pArena->pHeadSegment != IMG_NULL)
+		{
+			BT *pBT = pArena->pHeadSegment;
+			if (pBT->type != btt_free)
+			{
+				PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!"));
+				PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x" UINTPTR_FMT " size=0x%" SIZE_T_FMT_LEN "x", pBT->base, pBT->uSize));
+				return IMG_FALSE;
+			}
+		}
+	}
+
+	return IMG_TRUE;
+}
+
+/*!
+******************************************************************************
+	@Function       RA_Add
+
+	@Description    To add a resource span to an arena. The span must not
+                    overlapp with any span previously added to the arena.
+
+	@Input          pArena - the arena to add a span into.
+	@Input          base - the base of the span.
+	@Input          uSize - the extent of the span.
+
+	@Return         IMG_TRUE - Success
+                    IMG_FALSE - failure
+******************************************************************************/
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+	PVR_ASSERT (pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
+		return IMG_FALSE;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Add: name='%s', base=0x" UINTPTR_FMT ", size=0x%" SIZE_T_FMT_LEN "x", pArena->name, base, uSize));
+
+	uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
+	return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
+}
+
+/*!
+******************************************************************************
+	@Function       RA_Alloc
+
+	@Description    To allocate resource from an arena.
+
+	@Input          pArena - the arena
+	@Input          uRequestSize - the size of resource segment requested.
+	@Output         pActualSize - the actual size of resource segment
+                     allocated, typcially rounded up by quantum.
+	@Output         ppsMapping - the user reference associated with allocated resource span.
+	@Input          uFlags - flags influencing allocation policy.
+	@Input          uAlignment - the uAlignment constraint required for the
+	           	     allocated segment, use 0 if uAlignment not required.
+	@Input          uAlignmentOffset
+	@Input          pvPrivData - opaque private data passed through to allocator
+	@Input          ui32PrivDataLength - length of opaque private data
+
+	@Output         base - allocated base resource
+
+	@Return         IMG_TRUE - success
+                    IMG_FALSE - failure
+******************************************************************************/
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+		  IMG_SIZE_T uRequestSize,
+		  IMG_SIZE_T *pActualSize,
+		  BM_MAPPING **ppsMapping,
+		  IMG_UINT32 uFlags,
+		  IMG_UINT32 uAlignment,
+		  IMG_UINT32 uAlignmentOffset,
+		  IMG_PVOID pvPrivData,
+		  IMG_UINT32 ui32PrivDataLength,
+		  IMG_UINTPTR_T *base)
+{
+	IMG_BOOL bResult;
+	IMG_SIZE_T uSize = uRequestSize;
+
+	PVR_ASSERT (pArena!=IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
+		return IMG_FALSE;
+	}
+
+#if defined(VALIDATE_ARENA_TEST)
+	ValidateArena(pArena);
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+	CheckBMFreespace();
+#endif
+
+	if (pActualSize != IMG_NULL)
+	{
+		*pActualSize = uSize;
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Alloc: arena='%s', size=0x%" SIZE_T_FMT_LEN "x(0x%" SIZE_T_FMT_LEN "x), alignment=0x%x, offset=0x%x",
+		   pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
+
+	/* if allocation failed then we might have an import source which
+	   can provide more resource, else we will have to fail the
+	   allocation to the caller. */
+	bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
+									uAlignment, uAlignmentOffset, base);
+	if (!bResult)
+	{
+		BM_MAPPING *psImportMapping;
+		IMG_UINTPTR_T import_base;
+		IMG_SIZE_T uImportSize = uSize;
+
+		/*
+			Ensure that we allocate sufficient space to meet the uAlignment
+			constraint
+		 */
+		if (uAlignment > pArena->uQuantum)
+		{
+			uImportSize += (uAlignment - 1);
+		}
+
+		/* ensure that we import according to the quanta of this arena */
+		uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
+
+		bResult =
+			pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
+								  &psImportMapping, uFlags,
+								  pvPrivData, ui32PrivDataLength, &import_base);
+		if (bResult)
+		{
+			BT *pBT;
+			pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
+			/* successfully import more resource, create a span to
+			   represent it and retry the allocation attempt */
+			if (pBT == IMG_NULL)
+			{
+				/* insufficient resources to insert the newly acquired span,
+				   so free it back again */
+				pArena->pImportFree(pArena->pImportHandle, import_base,
+									psImportMapping);
+				PVR_DPF ((PVR_DBG_MESSAGE,
+						  "RA_Alloc: name='%s', size=0x%" SIZE_T_FMT_LEN "x failed!",
+						  pArena->name, uSize));
+				/* RA_Dump (arena); */
+				return IMG_FALSE;
+			}
+			pBT->psMapping = psImportMapping;
+#ifdef RA_STATS
+			pArena->sStatistics.uFreeSegmentCount++;
+			pArena->sStatistics.uFreeResourceCount += uImportSize;
+			pArena->sStatistics.uImportCount++;
+			pArena->sStatistics.uSpanCount++;
+#endif
+			bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
+										   uAlignment, uAlignmentOffset,
+										   base);
+			if (!bResult)
+			{
+				PVR_DPF ((PVR_DBG_MESSAGE,
+						  "RA_Alloc: name='%s' uAlignment failed!",
+						  pArena->name));
+			}
+		}
+	}
+#if defined PVRSRV_DEVMEM_TIME_STATS
+	else
+	{
+		/* If sub-allocation succeeded, the allocation was already mapped to Device MMU. So change timing to '0' */
+		if (ppsMapping)
+		{
+			(*ppsMapping)->ui32TimeToDevMap = 0;
+		}
+	}
+#endif
+
+#ifdef RA_STATS
+	if (bResult)
+	{
+		pArena->sStatistics.uCumulativeAllocs++;
+	}
+#endif
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Alloc: name='%s', size=0x%" SIZE_T_FMT_LEN "x, *base=0x" UINTPTR_FMT " = %d",
+			  pArena->name, uSize, *base, bResult));
+
+	/*  RA_Dump (pArena);
+		ra_stats (pArena);
+	*/
+
+#if defined(VALIDATE_ARENA_TEST)
+	ValidateArena(pArena);
+#endif
+
+	return bResult;
+}
+
+
+#if defined(VALIDATE_ARENA_TEST)
+
+/*!
+******************************************************************************
+	@Function       ValidateArena
+
+	@Description    Validate an arena by checking that adjacent members of the
+                    double linked ordered list are compatible. PVR_DBG_BREAK and
+                    PVR_DPF messages are used when an error is detected.
+                    NOTE: A DEBUG build is required for PVR_DBG_BREAK to operate.
+
+	@Input          pArena - the arena
+
+	@Return         0
+******************************************************************************/
+IMG_UINT32 ValidateArena(RA_ARENA *pArena)
+{
+	BT* pSegment;
+	RESOURCE_DESCRIPTOR eNextSpan;
+
+	pSegment = pArena->pHeadSegment;
+
+	if (pSegment == IMG_NULL)
+	{
+		return 0;
+	}
+
+	if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+	{
+		PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START);
+
+		while (pSegment->pNextSegment)
+		{
+			eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+			switch (pSegment->eResourceSpan)
+			{
+				case IMPORTED_RESOURCE_SPAN_LIVE:
+
+					if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+					{
+						/* error - next span must be live, free or end */
+						PVR_DPF((PVR_DBG_ERROR, 
+								"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT 
+								") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, 
+								pSegment->base, 
+								pSegment->pNextSegment->ui32BoundaryTagID, 
+								pSegment->pNextSegment->base, 
+								pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				case IMPORTED_RESOURCE_SPAN_FREE:
+
+					if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+					{
+						/* error - next span must be live or end */
+						PVR_DPF((PVR_DBG_ERROR, 
+								"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT
+								") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, 
+								pSegment->base, 
+								pSegment->pNextSegment->ui32BoundaryTagID, 
+								pSegment->pNextSegment->base, 
+								pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				case IMPORTED_RESOURCE_SPAN_END:
+
+					if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+						(eNextSpan == IMPORTED_RESOURCE_SPAN_END))
+					{
+						/* error - next span cannot be live, free or end */
+						PVR_DPF((PVR_DBG_ERROR, 
+								"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT
+								") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, 
+								pSegment->base, 
+								pSegment->pNextSegment->ui32BoundaryTagID, 
+								pSegment->pNextSegment->base, 
+								pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+
+				case IMPORTED_RESOURCE_SPAN_START:
+
+					if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+						  (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
+					{
+						/* error - next span must be live or free */
+						PVR_DPF((PVR_DBG_ERROR, 
+								"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT 
+								") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, 
+								pSegment->base, 
+								pSegment->pNextSegment->ui32BoundaryTagID, 
+								pSegment->pNextSegment->base, 
+								pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				default:
+					PVR_DPF((PVR_DBG_ERROR, 
+							"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT 
+							") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+							pSegment->ui32BoundaryTagID, 
+							pSegment->base, 
+							pSegment->pNextSegment->ui32BoundaryTagID, 
+							pSegment->pNextSegment->base, 
+							pArena->name));
+
+					PVR_DBG_BREAK;
+				break;
+			}
+			pSegment = pSegment->pNextSegment;
+		}
+	}
+	else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+	{
+		PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE));
+
+		while (pSegment->pNextSegment)
+		{
+			eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+			switch (pSegment->eResourceSpan)
+			{
+				case RESOURCE_SPAN_LIVE:
+
+					if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+						  (eNextSpan == RESOURCE_SPAN_LIVE)))
+					{
+						/* error - next span must be free or live */
+						PVR_DPF((PVR_DBG_ERROR, 
+								"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT 
+								") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, 
+								pSegment->base, 
+								pSegment->pNextSegment->ui32BoundaryTagID, 
+								pSegment->pNextSegment->base, 
+								pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				case RESOURCE_SPAN_FREE:
+
+					if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+						  (eNextSpan == RESOURCE_SPAN_LIVE)))
+					{
+						/* error - next span must be free or live */
+						PVR_DPF((PVR_DBG_ERROR, 
+								"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT 
+								") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, 
+								pSegment->base, 
+								pSegment->pNextSegment->ui32BoundaryTagID, 
+								pSegment->pNextSegment->base, 
+								pArena->name));
+
+						PVR_DBG_BREAK;
+					}
+				break;
+
+				default:
+					PVR_DPF((PVR_DBG_ERROR, 
+							"ValidateArena ERROR: adjacent boundary tags %d (base=0x" UINTPTR_FMT 
+							") and %d (base=0x" UINTPTR_FMT ") are incompatible (arena: %s)",
+								pSegment->ui32BoundaryTagID, 
+								pSegment->base, 
+								pSegment->pNextSegment->ui32BoundaryTagID, 
+								pSegment->pNextSegment->base, 
+								pArena->name));
+
+					PVR_DBG_BREAK;
+				break;
+			}
+			pSegment = pSegment->pNextSegment;
+		}
+
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized"));
+
+		PVR_DBG_BREAK;
+	}
+
+	return 0;
+}
+
+#endif
+
+
+/*!
+******************************************************************************
+	@Function       RA_Free
+
+	@Description    To free a resource segment.
+
+	@Input          pArena - the arena the segment was originally allocated from.
+	@Input          base - the base of the resource span to free.
+	@Input          bFreeBackingStore - Should backing store memory be freed.
+
+	@Return         None
+******************************************************************************/
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
+{
+	BT *pBT;
+
+	PVR_ASSERT (pArena != IMG_NULL);
+
+	if (pArena == IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
+		return;
+	}
+
+#ifdef USE_BM_FREESPACE_CHECK
+	CheckBMFreespace();
+#endif
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			  "RA_Free: name='%s', base=0x" UINTPTR_FMT, pArena->name, base));
+
+	pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
+	PVR_ASSERT (pBT != IMG_NULL);
+
+	if (pBT)
+	{
+		PVR_ASSERT (pBT->base == base);
+
+#ifdef RA_STATS
+		pArena->sStatistics.uCumulativeFrees++;
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+{
+	IMG_BYTE* p;
+	IMG_BYTE* endp;
+
+	p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+	endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize));
+	while ((IMG_UINT32)p & 3)
+	{
+		*p++ = 0xAA;
+	}
+	while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc))
+	{
+		*(IMG_UINT32*)p = 0xAAAAAAAA;
+		p += sizeof(IMG_UINT32);
+	}
+	while (p < endp)
+	{
+		*p++ = 0xAA;
+	}
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"BM_FREESPACE_CHECK: RA_Free Cleared %p to %p (size=0x%" SIZE_T_FMT_LEN "x)",
+			(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),
+			endp - 1,
+			pBT->uSize));
+}
+#endif
+		_FreeBT (pArena, pBT, bFreeBackingStore);
+	}
+}
+
+
+/*!
+******************************************************************************
+	@Function       RA_GetNextLiveSegment
+
+	@Description    Returns details of the next live resource segments
+
+	@Input          pArena - the arena the segment was originally allocated from.
+	@InOut          psSegDetails - rtn details of segments
+
+	@Return         IMG_TRUE if operation succeeded
+******************************************************************************/
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
+{
+	BT        *pBT;
+
+	if (psSegDetails->hSegment)
+	{
+		pBT = (BT *)psSegDetails->hSegment;
+	}
+	else
+	{
+		RA_ARENA *pArena = (RA_ARENA *)hArena;
+
+		pBT = pArena->pHeadSegment;
+	}
+	/* walk the arena segments and write live one to the  buffer */
+	while (pBT != IMG_NULL)
+	{
+		if (pBT->type == btt_live)
+		{
+			psSegDetails->uiSize = pBT->uSize;
+			psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
+			psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment;
+
+			return IMG_TRUE;
+		}
+
+		pBT = pBT->pNextSegment;
+	}
+
+	psSegDetails->uiSize = 0;
+	psSegDetails->sCpuPhyAddr.uiAddr = 0;
+	psSegDetails->hSegment = (IMG_HANDLE)IMG_UNDEF;
+
+	return IMG_FALSE;
+}
+
+
+#ifdef USE_BM_FREESPACE_CHECK
+RA_ARENA* pJFSavedArena = IMG_NULL;
+
+IMG_VOID CheckBMFreespace(IMG_VOID)
+{
+	BT *pBT;
+	IMG_BYTE* p;
+	IMG_BYTE* endp;
+
+	if (pJFSavedArena != IMG_NULL)
+	{
+		for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+		{
+			if (pBT->type == btt_free)
+			{
+				p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+				endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc);
+
+				while ((IMG_UINT32)p & 3)
+				{
+					if (*p++ != 0xAA)
+					{
+						fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+						for (;;);
+						break;
+					}
+				}
+				while (p < endp)
+				{
+					if (*(IMG_UINT32*)p != 0xAAAAAAAA)
+					{
+						fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+						for (;;);
+						break;
+					}
+					p += 4;
+				}
+			}
+		}
+	}
+}
+#endif
+
+
+#if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
+static IMG_CHAR *
+_BTType (IMG_INT eType)
+{
+	switch (eType)
+	{
+	case btt_span: return "span";
+	case btt_free: return "free";
+	case btt_live: return "live";
+	}
+	return "junk";
+}
+#endif /*defined(CONFIG_PROC_FS) && defined(DEBUG)*/
+
+#if defined(ENABLE_RA_DUMP)
+/*!
+******************************************************************************
+	@Function       RA_Dump
+
+	@Description    To dump a readable description of an arena. Diagnostic only.
+
+	@Input          pArena - the arena to dump.
+
+	@Return         None
+******************************************************************************/
+IMG_VOID
+RA_Dump (RA_ARENA *pArena)
+{
+	BT *pBT;
+	PVR_ASSERT (pArena != IMG_NULL);
+	PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name));
+	PVR_DPF ((PVR_DBG_MESSAGE,"  alloc=%p free=%p handle=%p quantum=%d",
+			 pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
+			 pArena->uQuantum));
+	PVR_DPF ((PVR_DBG_MESSAGE,"  segment Chain:"));
+	if (pArena->pHeadSegment != IMG_NULL &&
+	    pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+		PVR_DPF ((PVR_DBG_MESSAGE,"  error: head boundary tag has invalid pPrevSegment"));
+	if (pArena->pTailSegment != IMG_NULL &&
+	    pArena->pTailSegment->pNextSegment != IMG_NULL)
+		PVR_DPF ((PVR_DBG_MESSAGE,"  error: tail boundary tag has invalid pNextSegment"));
+
+	for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+	{
+		PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x" UINTPTR_FMT " size=0x%" SIZE_T_FMT_LEN "x type=%s",
+				 pBT->base, pBT->uSize, _BTType (pBT->type)));
+	}
+
+#ifdef HASH_TRACE
+	HASH_Dump (pArena->pSegmentHash);
+#endif
+}
+#endif /* #if defined(ENABLE_RA_DUMP) */
+
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el)
+{
+	RA_ARENA *pArena = (RA_ARENA *)PVRProcGetData(sfile->private);
+	IMG_UINTPTR_T off = (IMG_UINTPTR_T)el;
+
+	switch (off)
+	{
+	case 1:
+		seq_printf(sfile, "quantum\t\t\t%" SIZE_T_FMT_LEN "u\n", pArena->uQuantum);
+		break;
+	case 2:
+		seq_printf(sfile, "import_handle\t\t%p\n", pArena->pImportHandle);
+		break;
+#ifdef RA_STATS
+	case 3:
+		seq_printf(sfile,"span count\t\t%" SIZE_T_FMT_LEN "u\n", pArena->sStatistics.uSpanCount);
+		break;
+	case 4:
+		seq_printf(sfile, "live segment count\t%" SIZE_T_FMT_LEN "u\n", pArena->sStatistics.uLiveSegmentCount);
+		break;
+	case 5:
+		seq_printf(sfile, "free segment count\t%" SIZE_T_FMT_LEN "u\n", pArena->sStatistics.uFreeSegmentCount);
+		break;
+	case 6:
+		seq_printf(sfile, "free resource count\t%" SIZE_T_FMT_LEN "u (0x%" SIZE_T_FMT_LEN "x)\n",
+							pArena->sStatistics.uFreeResourceCount,
+							pArena->sStatistics.uFreeResourceCount);
+		break;
+	case 7:
+		seq_printf(sfile, "total allocs\t\t%" SIZE_T_FMT_LEN "u\n", pArena->sStatistics.uCumulativeAllocs);
+		break;
+	case 8:
+		seq_printf(sfile, "total frees\t\t%" SIZE_T_FMT_LEN "u\n", pArena->sStatistics.uCumulativeFrees);
+		break;
+	case 9:
+		seq_printf(sfile, "import count\t\t%" SIZE_T_FMT_LEN "u\n", pArena->sStatistics.uImportCount);
+		break;
+	case 10:
+		seq_printf(sfile, "export count\t\t%" SIZE_T_FMT_LEN "u\n", pArena->sStatistics.uExportCount);
+		break;
+#endif
+	}
+
+}
+
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off)
+{
+#ifdef RA_STATS
+	if(off <= 9)
+#else
+	if(off <= 1)
+#endif
+		return (void*)(IMG_UINTPTR_T)(off+1);
+	return 0;
+}
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el)
+{
+	RA_ARENA *pArena = (RA_ARENA *)PVRProcGetData(sfile->private);
+	BT *pBT = (BT*)el;
+
+	if (el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf(sfile, "Arena \"%s\"\nBase         Size Type Ref\n", pArena->name);
+		return;
+	}
+
+	if (pBT)
+	{
+		seq_printf(sfile, "%p %" SIZE_T_FMT_LEN "x %4s %p\n",
+				   (IMG_PVOID)pBT->base, pBT->uSize, _BTType (pBT->type),
+			       pBT->psMapping);
+	}
+}
+
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
+{
+	RA_ARENA *pArena = (RA_ARENA *)PVRProcGetData(sfile->private);
+	BT *pBT = 0;
+
+	if(off == 0)
+		return PVR_PROC_SEQ_START_TOKEN;
+
+	for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment);
+
+	return (void*)pBT;
+}
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
+
+
+#ifdef RA_STATS
+/*!
+******************************************************************************
+	@Function       RA_GetStats
+
+	@Description    Gets the arena stats and places in client buffer
+
+	@Input          pArena - the arena to print statistics for.
+	@Input          ppszStr - caller string to fill
+	@Input          pui32StrLen - length of caller string
+
+	@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+							IMG_CHAR **ppszStr,
+							IMG_UINT32 *pui32StrLen)
+{
+	IMG_CHAR 	*pszStr = *ppszStr;
+	IMG_UINT32 	ui32StrLen = *pui32StrLen;
+	IMG_INT32	i32Count;
+	BT 			*pBT;
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "  allocCB=%p freeCB=%p handle=%p quantum=%" SIZE_T_FMT_LEN "u\n",
+							 pArena->pImportAlloc,
+							 pArena->pImportFree,
+							 pArena->pImportHandle,
+							 pArena->uQuantum);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%" SIZE_T_FMT_LEN "u\n", 
+                             pArena->sStatistics.uSpanCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%" SIZE_T_FMT_LEN "u\n", 
+                             pArena->sStatistics.uLiveSegmentCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%" SIZE_T_FMT_LEN "u\n", 
+                             pArena->sStatistics.uFreeSegmentCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%" SIZE_T_FMT_LEN "u (0x%" SIZE_T_FMT_LEN "x)\n",
+							pArena->sStatistics.uFreeResourceCount,
+							pArena->sStatistics.uFreeResourceCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%" SIZE_T_FMT_LEN "u\n", 
+                            pArena->sStatistics.uCumulativeAllocs);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%" SIZE_T_FMT_LEN "u\n", 
+                            pArena->sStatistics.uCumulativeFrees);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%" SIZE_T_FMT_LEN "u\n", 
+                            pArena->sStatistics.uImportCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%" SIZE_T_FMT_LEN "u\n", 
+                            pArena->sStatistics.uExportCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "  segment Chain:\n");
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+	if (pArena->pHeadSegment != IMG_NULL &&
+	    pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+	{
+		CHECK_SPACE(ui32StrLen);
+		i32Count = OSSNPrintf(pszStr, 100, "  error: head boundary tag has invalid pPrevSegment\n");
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	if (pArena->pTailSegment != IMG_NULL &&
+	    pArena->pTailSegment->pNextSegment != IMG_NULL)
+	{
+		CHECK_SPACE(ui32StrLen);
+		i32Count = OSSNPrintf(pszStr, 100, "  error: tail boundary tag has invalid pNextSegment\n");
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+	{
+		CHECK_SPACE(ui32StrLen);
+		i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%p size=0x%" SIZE_T_FMT_LEN "x type=%s ref=%p\n",
+											 (void *)pBT->base,
+											 pBT->uSize,
+											 _BTType(pBT->type),
+											 pBT->psMapping);
+		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	}
+
+	*ppszStr = pszStr;
+	*pui32StrLen = ui32StrLen;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+								IMG_CHAR **ppszStr, 
+								IMG_UINT32 *pui32StrLen)
+{
+	IMG_CHAR 	*pszStr = *ppszStr;
+	IMG_UINT32 	ui32StrLen = *pui32StrLen;
+	IMG_INT32	i32Count;
+	CHECK_SPACE(ui32StrLen);
+	i32Count = OSSNPrintf(pszStr, 100, "Bytes free: Arena %-30s: %" SIZE_T_FMT_LEN "u (0x%" SIZE_T_FMT_LEN "x)\n", pArena->name,
+		pArena->sStatistics.uFreeResourceCount,
+		pArena->sStatistics.uFreeResourceCount);
+	UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+	*ppszStr = pszStr;
+	*pui32StrLen = ui32StrLen;
+	
+	return PVRSRV_OK;
+}
+#endif
+
+/******************************************************************************
+ End of file (ra.c)
+******************************************************************************/
+
+
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/common/refcount.c b/drivers/gpu/pvr/services4/srvkm/common/refcount.c
new file mode 100644
index 0000000..aacb94c
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/refcount.c
@@ -0,0 +1,760 @@
+/*************************************************************************/ /*!
+@Title          Services reference count debugging
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+#include "services_headers.h"
+
+#ifndef __linux__
+#warning Reference count debugging is not thread-safe on this platform
+#define PVRSRV_LOCK_CCB()
+#define PVRSRV_UNLOCK_CCB()
+#else /* __linux__ */
+#include <linux/spinlock.h>
+static DEFINE_SPINLOCK(gsCCBLock);
+#define PVRSRV_LOCK_CCB() \
+	{ \
+		unsigned long flags; \
+		spin_lock_irqsave(&gsCCBLock, flags);
+#define PVRSRV_UNLOCK_CCB()	\
+		spin_unlock_irqrestore(&gsCCBLock, flags); \
+	}
+#endif /* __linux__ */
+
+#define PVRSRV_REFCOUNT_CCB_MAX			512
+#define PVRSRV_REFCOUNT_CCB_MESG_MAX	80
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO	(1U << 0)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO	(1U << 1)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF	(1U << 2)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2	(1U << 3)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC	(1U << 4)
+
+#if defined(__linux__)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP		(1U << 16)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2		(1U << 17)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_ION_SYNC	(1U << 18)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_DMABUF_SYNC	(1U << 19)
+#else
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP		0
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2		0
+#define PVRSRV_REFCOUNT_CCB_DEBUG_ION_SYNC	0
+#define PVRSRV_REFCOUNT_CCB_DEBUG_DMABUF_SYNC	0
+#endif
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_ALL		~0U
+
+/*static const IMG_UINT guiDebugMask = PVRSRV_REFCOUNT_CCB_DEBUG_ALL;*/
+static const IMG_UINT guiDebugMask =
+	PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO |
+#if defined(SUPPORT_ION)
+	PVRSRV_REFCOUNT_CCB_DEBUG_ION_SYNC |
+#endif
+#if defined(SUPPORT_DMABUF)
+	PVRSRV_REFCOUNT_CCB_DEBUG_DMABUF_SYNC |
+#endif
+	PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2;
+
+typedef struct
+{
+	const IMG_CHAR *pszFile;
+	IMG_INT iLine;
+	IMG_UINT32 ui32PID;
+	IMG_CHAR pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX];
+}
+PVRSRV_REFCOUNT_CCB;
+
+static PVRSRV_REFCOUNT_CCB gsRefCountCCB[PVRSRV_REFCOUNT_CCB_MAX];
+static IMG_UINT giOffset;
+
+static const IMG_CHAR gszHeader[] =
+	/*        10        20        30        40        50        60        70
+	 * 345678901234567890123456789012345678901234567890123456789012345678901
+	 */
+	"TYPE     SYNCINFO MEMINFO  MEMHANDLE OTHER    REF  REF' SIZE     PID";
+	/* NCINFO deadbeef deadbeef deadbeef  deadbeef 1234 1234 deadbeef */
+
+#define PVRSRV_REFCOUNT_CCB_FMT_STRING "%8.8s %8p %8p %8p  %8p %.4d %.4d %.8x"
+
+IMG_INTERNAL
+void PVRSRVDumpRefCountCCB(void)
+{
+	int i;
+
+	PVRSRV_LOCK_CCB();
+
+	PVR_LOG(("%s", gszHeader));
+
+	for(i = 0; i < PVRSRV_REFCOUNT_CCB_MAX; i++)
+	{
+		PVRSRV_REFCOUNT_CCB *psRefCountCCBEntry =
+			&gsRefCountCCB[(giOffset + i) % PVRSRV_REFCOUNT_CCB_MAX];
+
+		/* Early on, we won't have MAX_REFCOUNT_CCB_SIZE messages */
+		if(!psRefCountCCBEntry->pszFile)
+			continue;
+
+		PVR_LOG(("%s %d %s:%d", psRefCountCCBEntry->pcMesg,
+								psRefCountCCBEntry->ui32PID,
+								psRefCountCCBEntry->pszFile,
+								psRefCountCCBEntry->iLine));
+	}
+
+	PVRSRV_UNLOCK_CCB();
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								 PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+								 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "SYNCINFO",
+			 psKernelSyncInfo,
+			 psKernelMemInfo,
+			 NULL,
+			 (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+			 ui32RefValue,
+			 ui32RefValue + 1,
+			 (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								 PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+								 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "SYNCINFO",
+			 psKernelSyncInfo,
+			 psKernelMemInfo,
+			 (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+			 NULL,
+			 ui32RefValue,
+			 ui32RefValue - 1,
+			 (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "MEMINFO",
+			 psKernelMemInfo->psKernelSyncInfo,
+			 psKernelMemInfo,
+			 psKernelMemInfo->sMemBlk.hOSMemHandle,
+			 NULL,
+			 psKernelMemInfo->ui32RefCount,
+			 psKernelMemInfo->ui32RefCount + 1,
+			 psKernelMemInfo->uAllocSize);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	psKernelMemInfo->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "MEMINFO",
+			 psKernelMemInfo->psKernelSyncInfo,
+			 psKernelMemInfo,
+			 psKernelMemInfo->sMemBlk.hOSMemHandle,
+			 NULL,
+			 psKernelMemInfo->ui32RefCount,
+			 psKernelMemInfo->ui32RefCount - 1,
+			 psKernelMemInfo->uAllocSize);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	psKernelMemInfo->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "BM_BUF",
+			 NULL,
+			 NULL,
+			 BM_HandleToOSMemHandle(pBuf),
+			 pBuf,
+			 pBuf->ui32RefCount,
+			 pBuf->ui32RefCount + 1,
+			 (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	pBuf->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "BM_BUF",
+			 NULL,
+			 NULL,
+			 BM_HandleToOSMemHandle(pBuf),
+			 pBuf,
+			 pBuf->ui32RefCount,
+			 pBuf->ui32RefCount - 1,
+			 (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	pBuf->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "BM_BUF2",
+			 NULL,
+			 NULL,
+			 BM_HandleToOSMemHandle(pBuf),
+			 pBuf,
+			 pBuf->ui32ExportCount,
+			 pBuf->ui32ExportCount + 1,
+			 (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	pBuf->ui32ExportCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "BM_BUF2",
+			 NULL,
+			 NULL,
+			 BM_HandleToOSMemHandle(pBuf),
+			 pBuf,
+			 pBuf->ui32ExportCount,
+			 pBuf->ui32ExportCount - 1,
+			 (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	pBuf->ui32ExportCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "BM_XPROC",
+			 NULL,
+			 NULL,
+			 gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+			 (IMG_VOID *) ui32Index,
+			 gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+			 gXProcWorkaroundShareData[ui32Index].ui32RefCount + 1,
+			 gXProcWorkaroundShareData[ui32Index].ui32Size);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "BM_XPROC",
+			 NULL,
+			 NULL,
+			 gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+			 (IMG_VOID *) ui32Index,
+			 gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+			 gXProcWorkaroundShareData[ui32Index].ui32RefCount - 1,
+			 gXProcWorkaroundShareData[ui32Index].ui32Size);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+							   PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "MMAP",
+			 NULL,
+			 NULL,
+			 psOffsetStruct->psLinuxMemArea,
+			 psOffsetStruct,
+			 psOffsetStruct->ui32RefCount,
+			 psOffsetStruct->ui32RefCount + 1,
+			 psOffsetStruct->uiRealByteSize);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	psOffsetStruct->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+							   PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "MMAP",
+			 NULL,
+			 NULL,
+			 psOffsetStruct->psLinuxMemArea,
+			 psOffsetStruct,
+			 psOffsetStruct->ui32RefCount,
+			 psOffsetStruct->ui32RefCount - 1,
+			 psOffsetStruct->uiRealByteSize);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	psOffsetStruct->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								  PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "MMAP2",
+			 NULL,
+			 NULL,
+			 psOffsetStruct->psLinuxMemArea,
+			 psOffsetStruct,
+			 psOffsetStruct->ui32Mapped,
+			 psOffsetStruct->ui32Mapped + 1,
+			 psOffsetStruct->uiRealByteSize);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	psOffsetStruct->ui32Mapped++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								  PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "MMAP2",
+			 NULL,
+			 NULL,
+			 psOffsetStruct->psLinuxMemArea,
+			 psOffsetStruct,
+			 psOffsetStruct->ui32Mapped,
+			 psOffsetStruct->ui32Mapped - 1,
+			 psOffsetStruct->uiRealByteSize);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+
+skip:
+	psOffsetStruct->ui32Mapped--;
+}
+
+#if defined(SUPPORT_ION)
+PVRSRV_ERROR PVRSRVIonBufferSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+											IMG_HANDLE hUnique,
+											IMG_HANDLE hDevCookie,
+											IMG_HANDLE hDevMemContext,
+											PVRSRV_ION_SYNC_INFO **ppsIonSyncInfo,
+											PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVRSRV_ERROR eError;
+
+	/*
+		We have to do the call 1st as we need to Ion syninfo which it returns
+	*/
+	eError = PVRSRVIonBufferSyncAcquire(hUnique,
+										hDevCookie,
+										hDevMemContext,
+										ppsIonSyncInfo);
+
+	if (eError == PVRSRV_OK)
+	{
+		if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_ION_SYNC))
+			goto skip;
+
+		PVRSRV_LOCK_CCB();
+
+		gsRefCountCCB[giOffset].pszFile = pszFile;
+		gsRefCountCCB[giOffset].iLine = iLine;
+		gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+		snprintf(gsRefCountCCB[giOffset].pcMesg,
+				 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+				 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+				 "ION_SYNC",
+				 (*ppsIonSyncInfo)->psSyncInfo,
+				 psKernelMemInfo,
+				 NULL,
+				 *ppsIonSyncInfo,
+				 (*ppsIonSyncInfo)->ui32RefCount - 1,
+				 (*ppsIonSyncInfo)->ui32RefCount,
+				 0);
+		gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+		giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+		PVRSRV_UNLOCK_CCB();
+	}
+
+skip:
+	return eError;
+}
+
+void PVRSRVIonBufferSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+									PVRSRV_ION_SYNC_INFO *psIonSyncInfo,
+									PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_ION_SYNC))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "ION_SYNC",
+			 psIonSyncInfo->psSyncInfo,
+			 psKernelMemInfo,
+			 NULL,
+			 psIonSyncInfo,
+			 psIonSyncInfo->ui32RefCount,
+			 psIonSyncInfo->ui32RefCount - 1,
+			 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+skip:
+	PVRSRVIonBufferSyncRelease(psIonSyncInfo);
+}
+
+#endif /* defined (SUPPORT_ION) */
+
+#if defined(SUPPORT_DMABUF)
+PVRSRV_ERROR PVRSRVDmaBufSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+											IMG_HANDLE hUnique,
+											IMG_HANDLE hPriv,
+											IMG_HANDLE hDevCookie,
+											IMG_HANDLE hDevMemContext,
+											PVRSRV_DMABUF_SYNC_INFO **ppsDmaBufSyncInfo,
+											PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVRSRV_ERROR eError;
+
+	eError = PVRSRVDmaBufSyncAcquire(hUnique,
+										hPriv,
+										hDevCookie,
+										hDevMemContext,
+										ppsDmaBufSyncInfo);
+
+	if (eError == PVRSRV_OK)
+	{
+		if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_DMABUF_SYNC))
+			goto skip;
+
+		PVRSRV_LOCK_CCB();
+
+		gsRefCountCCB[giOffset].pszFile = pszFile;
+		gsRefCountCCB[giOffset].iLine = iLine;
+		gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+		snprintf(gsRefCountCCB[giOffset].pcMesg,
+				 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+				 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+				 "DMA-BUF_SYNC",
+				 (*ppsDmaBufSyncInfo)->psSyncInfo,
+				 psKernelMemInfo,
+				 NULL,
+				 *ppsDmaBufSyncInfo,
+				 (*ppsDmaBufSyncInfo)->ui32RefCount - 1,
+				 (*ppsDmaBufSyncInfo)->ui32RefCount,
+				 0);
+		gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+		giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+		PVRSRV_UNLOCK_CCB();
+	}
+
+skip:
+	return eError;
+}
+
+void PVRSRVDmaBufSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+									PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo,
+									PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_DMABUF_SYNC))
+		goto skip;
+
+	PVRSRV_LOCK_CCB();
+
+	gsRefCountCCB[giOffset].pszFile = pszFile;
+	gsRefCountCCB[giOffset].iLine = iLine;
+	gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+	snprintf(gsRefCountCCB[giOffset].pcMesg,
+			 PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+			 PVRSRV_REFCOUNT_CCB_FMT_STRING,
+			 "DMA-BUF_SYNC",
+			 psDmaBufSyncInfo->psSyncInfo,
+			 psKernelMemInfo,
+			 NULL,
+			 psDmaBufSyncInfo,
+			 psDmaBufSyncInfo->ui32RefCount,
+			 psDmaBufSyncInfo->ui32RefCount - 1,
+			 0);
+	gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+	giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+	PVRSRV_UNLOCK_CCB();
+skip:
+	PVRSRVDmaBufSyncRelease(psDmaBufSyncInfo);
+}
+#endif /* defined (SUPPORT_DMABUF) */
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
diff --git a/drivers/gpu/pvr/services4/srvkm/common/resman.c b/drivers/gpu/pvr/services4/srvkm/common/resman.c
new file mode 100644
index 0000000..a8b8a2f
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/resman.c
@@ -0,0 +1,990 @@
+/*************************************************************************/ /*!
+@Title          Resource Manager
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provide resource management
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#include "services_headers.h"
+#include "resman.h"
+
+#ifdef __linux__
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+#include <linux/hardirq.h>
+#else
+#include <asm/hardirq.h>
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+#include <linux/mutex.h>
+#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+static DEFINE_MUTEX(lock);
+#define	DOWN(m) mutex_lock(m)
+#define	UP(m) mutex_unlock(m)
+#else
+static DECLARE_MUTEX(lock);
+#define	DOWN(m) down(m)
+#define	UP(m) up(m)
+#endif
+
+#define ACQUIRE_SYNC_OBJ  do {							\
+		if (in_interrupt()) { 							\
+			printk("ISR cannot take RESMAN mutex\n"); 	\
+			BUG(); 										\
+		} 												\
+		else DOWN(&lock); 								\
+} while (0)
+#define RELEASE_SYNC_OBJ UP(&lock)
+
+#else
+
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+#endif
+
+#define RESMAN_SIGNATURE 0x12345678
+
+/******************************************************************************
+ * resman structures
+ *****************************************************************************/
+
+/* resman item structure */
+typedef struct _RESMAN_ITEM_
+{
+#ifdef DEBUG
+	IMG_UINT32				ui32Signature;
+#endif
+	struct _RESMAN_ITEM_	**ppsThis;	/*!< list navigation */
+	struct _RESMAN_ITEM_	*psNext;	/*!< list navigation */
+
+	IMG_UINT32				ui32Flags;	/*!< flags */
+	IMG_UINT32				ui32ResType;/*!< res type */
+
+	IMG_PVOID				pvParam;	/*!< param1 for callback */
+	IMG_UINT32				ui32Param;	/*!< param2 for callback */
+
+	RESMAN_FREE_FN			pfnFreeResource;/*!< resman item free callback */
+} RESMAN_ITEM;
+
+
+/* resman context structure */
+typedef struct _RESMAN_CONTEXT_
+{
+#ifdef DEBUG
+	IMG_UINT32					ui32Signature;
+#endif
+	struct	_RESMAN_CONTEXT_	**ppsThis;/*!< list navigation */
+	struct	_RESMAN_CONTEXT_	*psNext;/*!< list navigation */
+
+	PVRSRV_PER_PROCESS_DATA		*psPerProc; /* owner of resources */
+
+	RESMAN_ITEM					*psResItemList;/*!< res item list for context */
+
+} RESMAN_CONTEXT;
+
+
+/* resman list structure */
+typedef struct
+{
+	RESMAN_CONTEXT	*psContextList; /*!< resman context list */
+
+} RESMAN_LIST, *PRESMAN_LIST;	/* PRQA S 3205 */
+
+
+PRESMAN_LIST	gpsResList = IMG_NULL;
+
+#include "lists.h"	/* PRQA S 5087 */ /* include lists.h required here */
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+static IMPLEMENT_LIST_REVERSE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+
+#define PRINT_RESLIST(x, y, z)
+
+/******************************************************** Forword references */
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback, IMG_BOOL bForceCleanup);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT	psContext,
+										   IMG_UINT32		ui32SearchCriteria,
+										   IMG_UINT32		ui32ResType,
+										   IMG_PVOID		pvParam,
+										   IMG_UINT32		ui32Param,
+										   IMG_BOOL			bExecuteCallback);
+
+
+#ifdef DEBUG
+	static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
+	#define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+	#define VALIDATERESLIST()
+#endif
+
+
+
+
+
+
+/*!
+******************************************************************************
+
+ @Function	ResManInit
+
+ @Description initialises the resman
+
+ @Return   none
+
+******************************************************************************/
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+	if (gpsResList == IMG_NULL)
+	{
+		/* If not already initialised */
+		if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(*gpsResList),
+						(IMG_VOID **)&gpsResList, IMG_NULL,
+						"Resource Manager List") != PVRSRV_OK)
+		{
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+		/* Init list, the linked list has dummy entries at both ends */
+		gpsResList->psContextList = IMG_NULL;
+
+		/* Check resource list */
+		VALIDATERESLIST();
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	ResManDeInit
+
+ @Description de-initialises the resman
+
+ @Return   none
+
+******************************************************************************/
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+	if (gpsResList != IMG_NULL)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
+		gpsResList = IMG_NULL;
+	}
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVResManConnect
+
+ @Description Opens a connection to the Resource Manager
+
+ @input 	hPerProc - Per-process data (if applicable)
+ @output 	phResManContext - Resman context
+
+ @Return    error code or PVRSRV_OK
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE			hPerProc,
+								 PRESMAN_CONTEXT	*phResManContext)
+{
+	PVRSRV_ERROR	eError;
+	PRESMAN_CONTEXT	psResManContext;
+
+	/*Acquire resource list sync object*/
+	ACQUIRE_SYNC_OBJ;
+
+	/*Check resource list*/
+	VALIDATERESLIST();
+
+	/* Allocate memory for the new context. */
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+						(IMG_VOID **)&psResManContext, IMG_NULL,
+						"Resource Manager Context");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+
+		/* Check resource list */
+		VALIDATERESLIST();
+
+		/* Release resource list sync object */
+		RELEASE_SYNC_OBJ;
+
+		return eError;
+	}
+
+#ifdef DEBUG
+	psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif /* DEBUG */
+	psResManContext->psResItemList	= IMG_NULL;
+	psResManContext->psPerProc = hPerProc;
+
+	/* Insert new context struct after the dummy first entry */
+	List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
+
+	/* Check resource list */
+	VALIDATERESLIST();
+
+	/* Release resource list sync object */
+	RELEASE_SYNC_OBJ;
+
+	*phResManContext = psResManContext;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVResManDisconnect
+
+ @Description Closes a Resource Manager connection and frees all resources
+
+ @input 	hResManContext - Resman context
+ @input 	bKernelContext - IMG_TRUE for kernel contexts
+
+ @Return	IMG_VOID
+
+******************************************************************************/
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
+								IMG_BOOL		bKernelContext)
+{
+	/* Acquire resource list sync object */
+	ACQUIRE_SYNC_OBJ;
+
+	/* Check resource list */
+	VALIDATERESLIST();
+
+	/* Print and validate resource list */
+	PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
+
+	/* Free all auto-freed resources in order */
+
+	if (!bKernelContext)
+	{
+		/* OS specific User-mode Mappings: */
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
+
+		/* VGX types: */
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DMA_CLIENT_FIFO_DATA, 0, 0, IMG_TRUE);
+
+		/* Event Object */
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
+
+		/* syncobject state (Read/Write Complete values) */
+		/* Must be FIFO, so we reverse the list, twice */
+		List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
+		List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);  // (could survive without this - all following items would be cleared up "fifo" too)
+
+		/* SGX types: */
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
+		
+		/* COMMON types: */
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SYNC_INFO, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+#if defined(SUPPORT_ION)
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ION, 0, 0, IMG_TRUE);
+#endif
+#if defined(SUPPORT_DMABUF)
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_DMABUF, 0, 0, IMG_TRUE);
+#endif
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_MEM_INFO, 0, 0, IMG_TRUE);
+
+		/* DISPLAY CLASS types: */
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+		/* BUFFER CLASS types: */
+		FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
+	}
+
+	/* Ensure that there are no resources left */
+	PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+	/* Remove the context struct from the list */
+	List_RESMAN_CONTEXT_Remove(psResManContext);
+
+	/* Free the context struct */
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+
+	/* Check resource list */
+	VALIDATERESLIST();
+
+	/* Print and validate resource list */
+	PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
+
+	/* Release resource list sync object */
+	RELEASE_SYNC_OBJ;
+}
+
+
+/*!
+******************************************************************************
+ @Function	 ResManRegisterRes
+
+ @Description    : Inform the resource manager that the given resource has
+				   been alloacted and freeing of it will be the responsibility
+				   of the resource manager
+
+ @input 	psResManContext - resman context
+ @input 	ui32ResType - identify what kind of resource it is
+ @input 	pvParam - address of resource
+ @input 	ui32Param - size of resource
+ @input 	pfnFreeResource - pointer to function that frees this resource
+
+ @Return   On success a pointer to an opaque data structure that represents
+						the allocated resource, else NULL
+
+**************************************************************************/
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT	psResManContext,
+							   IMG_UINT32		ui32ResType,
+							   IMG_PVOID		pvParam,
+							   IMG_UINT32		ui32Param,
+							   RESMAN_FREE_FN	pfnFreeResource)
+{
+	PRESMAN_ITEM	psNewResItem;
+
+	PVR_ASSERT(psResManContext != IMG_NULL);
+	PVR_ASSERT(ui32ResType != 0);
+
+	if (psResManContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+		return (PRESMAN_ITEM) IMG_NULL;
+	}
+
+	/* Acquire resource list sync object */
+	ACQUIRE_SYNC_OBJ;
+
+	/* Check resource list */
+	VALIDATERESLIST();
+
+	PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+			"Context 0x%p, ResType 0x%x, pvParam 0x%p, ui32Param 0x%x, "
+			"FreeFunc %p",
+			psResManContext,
+			ui32ResType,
+			pvParam,
+			ui32Param,
+			pfnFreeResource));
+
+	/* Allocate memory for the new resource structure */
+	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				   sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
+				   IMG_NULL,
+				   "Resource Manager Item") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+				"ERROR allocating new resource item"));
+
+		/* Release resource list sync object */
+		RELEASE_SYNC_OBJ;
+
+		return((PRESMAN_ITEM)IMG_NULL);
+	}
+
+	/* Fill in details about this resource */
+#ifdef DEBUG
+	psNewResItem->ui32Signature		= RESMAN_SIGNATURE;
+#endif /* DEBUG */
+	psNewResItem->ui32ResType		= ui32ResType;
+	psNewResItem->pvParam			= pvParam;
+	psNewResItem->ui32Param			= ui32Param;
+	psNewResItem->pfnFreeResource	= pfnFreeResource;
+	psNewResItem->ui32Flags		    = 0;
+
+	/* Insert new structure after dummy first entry */
+	List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+	/* Check resource list */
+	VALIDATERESLIST();
+
+	/* Release resource list sync object */
+	RELEASE_SYNC_OBJ;
+
+	return(psNewResItem);
+}
+
+/*!
+******************************************************************************
+ @Function	 	ResManFreeResByPtr
+
+ @Description   frees a resource by matching on pointer type
+
+ @inputs        psResItem - pointer to resource item to free
+                bForceCleanup	- ignored uKernel re-sync
+
+ @Return   		PVRSRV_ERROR
+**************************************************************************/
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM	*psResItem, IMG_BOOL bForceCleanup)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_ASSERT(psResItem != IMG_NULL);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+		return PVRSRV_OK;
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %p",
+			psResItem));
+
+	/*Acquire resource list sync object*/
+	ACQUIRE_SYNC_OBJ;
+
+	/*Check resource list*/
+	VALIDATERESLIST();
+
+	/*Free resource*/
+	eError = FreeResourceByPtr(psResItem, IMG_TRUE, bForceCleanup);
+
+	/*Check resource list*/
+	VALIDATERESLIST();
+
+	/*Release resource list sync object*/
+	RELEASE_SYNC_OBJ;
+
+	return(eError);
+}
+
+
+/*!
+******************************************************************************
+ @Function	 	ResManFreeResByCriteria
+
+ @Description   frees a resource by matching on criteria
+
+ @inputs	 	hResManContext - handle for resman context
+ @inputs        ui32SearchCriteria - indicates which parameters should be
+ 				used in search for resources to free
+ @inputs        ui32ResType - identify what kind of resource to free
+ @inputs        pvParam - address of resource to be free
+ @inputs        ui32Param - size of resource to be free
+
+ @Return   		PVRSRV_ERROR
+**************************************************************************/
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT	psResManContext,
+									 IMG_UINT32			ui32SearchCriteria,
+									 IMG_UINT32			ui32ResType,
+									 IMG_PVOID			pvParam,
+									 IMG_UINT32			ui32Param)
+{
+	PVRSRV_ERROR	eError;
+
+	PVR_ASSERT(psResManContext != IMG_NULL);
+
+	/* Acquire resource list sync object */
+	ACQUIRE_SYNC_OBJ;
+
+	/* Check resource list */
+	VALIDATERESLIST();
+
+	PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+			"Context 0x%p, Criteria 0x%x, Type 0x%x, Addr 0x%p, Param 0x%x",
+			psResManContext, ui32SearchCriteria, ui32ResType,
+			pvParam, ui32Param));
+
+	/* Free resources by criteria for this context */
+	eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+									ui32ResType, pvParam, ui32Param,
+									IMG_TRUE);
+
+	/* Check resource list */
+	VALIDATERESLIST();
+
+	/* Release resource list sync object */
+	RELEASE_SYNC_OBJ;
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+ @Function	 	ResManDissociateRes
+
+ @Description   Moves a resource from one context to another.
+
+ @inputs        psResItem - pointer to resource item to dissociate
+ @inputs	 	psNewResManContext - new resman context for the resource
+
+ @Return   		IMG_VOID
+**************************************************************************/
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM		*psResItem,
+							 PRESMAN_CONTEXT	psNewResManContext)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT(psResItem != IMG_NULL);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#ifdef DEBUG /* QAC fix */
+	PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+	if (psNewResManContext != IMG_NULL)
+	{
+		/* Remove this item from its old resource list */
+		List_RESMAN_ITEM_Remove(psResItem);
+
+		/* Re-insert into new list */
+		List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+	}
+	else
+	{
+		eError = FreeResourceByPtr(psResItem, IMG_FALSE, CLEANUP_WITH_POLL);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
+			return eError;
+		}
+	}
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+ @Function	 	ResManFindResourceByPtr_AnyVaCb
+
+ @Description
+ 					Compares the resman item with a given pointer.
+
+ @inputs	 	psCurItem - theThe item to check
+ @inputs        va - Variable argument list with:
+					 psItem - pointer to resource item to find
+
+ @Return   		IMG_BOOL
+**************************************************************************/
+static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+	RESMAN_ITEM		*psItem;
+
+	psItem = va_arg(va, RESMAN_ITEM*);
+
+	return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+/*!
+******************************************************************************
+ @Function	 	ResManFindResourceByPtr
+
+ @Description
+ 					Attempts to find a resource in the list for this context
+
+ @inputs	 	hResManContext - handle for resman context
+ @inputs        psItem - pointer to resource item to find
+
+ @Return   		PVRSRV_ERROR
+**************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT	psResManContext,
+												  RESMAN_ITEM		*psItem)
+{
+/*	RESMAN_ITEM		*psCurItem;*/
+
+	PVRSRV_ERROR	eResult;
+
+	PVR_ASSERT(psResManContext != IMG_NULL);
+	PVR_ASSERT(psItem != IMG_NULL);
+
+	if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+		PVR_DBG_BREAK;
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#ifdef DEBUG	/* QAC fix */
+	PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+	/* Acquire resource list sync object */
+	ACQUIRE_SYNC_OBJ;
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FindResourceByPtr: psItem=%p, psItem->psNext=%p",
+			psItem, psItem->psNext));
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FindResourceByPtr: Resource Ctx 0x%p, Type 0x%x, Addr 0x%p, "
+			"Param 0x%x, FnCall %p, Flags 0x%x",
+			psResManContext,
+			psItem->ui32ResType,
+			psItem->pvParam,
+			psItem->ui32Param,
+			psItem->pfnFreeResource,
+			psItem->ui32Flags));
+
+	/* Search resource items starting at after the first dummy item */
+	if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+										&ResManFindResourceByPtr_AnyVaCb,
+										psItem))
+	{
+		eResult = PVRSRV_OK;
+	}
+	else
+	{
+		eResult = PVRSRV_ERROR_NOT_OWNER;
+	}
+
+	/* Release resource list sync object */
+	RELEASE_SYNC_OBJ;
+
+/*	return PVRSRV_ERROR_NOT_OWNER;*/
+	return eResult;
+}
+
+/*!
+******************************************************************************
+ @Function	 	FreeResourceByPtr
+
+ @Description
+ 					Frees a resource and move it from the list
+					NOTE : this function must be called with the resource
+					list sync object held
+
+ @inputs        psItem - pointer to resource item to free
+ 				bExecuteCallback - execute callback?
+ 				bForceCleanup - skips uKernel re-sync
+
+ @Return   		PVRSRV_ERROR
+**************************************************************************/
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM	*psItem,
+									  IMG_BOOL		bExecuteCallback,
+									  IMG_BOOL		bForceCleanup)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_ASSERT(psItem != IMG_NULL);
+
+	if (psItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+#ifdef DEBUG	/* QAC fix */
+	PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FreeResourceByPtr: psItem=%p, psItem->psNext=%p",
+			psItem, psItem->psNext));
+
+	PVR_DPF((PVR_DBG_MESSAGE,
+			"FreeResourceByPtr: Type 0x%x, Addr 0x%p, "
+			"Param 0x%x, FnCall %p, Flags 0x%x",
+			psItem->ui32ResType,
+			psItem->pvParam, 
+            psItem->ui32Param,
+			psItem->pfnFreeResource, psItem->ui32Flags));
+
+	/* Release resource list sync object just in case the free routine calls the resource manager */
+	RELEASE_SYNC_OBJ;
+
+	/* Call the freeing routine */
+	if (bExecuteCallback)
+	{
+		eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param, bForceCleanup);
+	 	if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
+		}
+	}
+
+	/* Acquire resource list sync object */
+	ACQUIRE_SYNC_OBJ;
+
+	if (eError != PVRSRV_ERROR_RETRY)
+	{
+		/* Remove this item from the resource list */
+		List_RESMAN_ITEM_Remove(psItem);
+
+		/* Free memory for the resource item */
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+	}
+
+	return(eError);
+}
+
+/*!
+******************************************************************************
+ @Function	 	FreeResourceByCriteria_AnyVaCb
+
+ @Description
+ 					Matches a resource manager item with a given criteria.
+
+ @inputs        psCuItem - the item to be matched
+ @inputs		va - a variable argument list with:.
+					ui32SearchCriteria - indicates which parameters should be used
+					search for resources to free
+					ui32ResType - identify what kind of resource to free
+					pvParam - address of resource to be free
+					ui32Param - size of resource to be free
+
+
+ @Return   		psCurItem if matched, IMG_NULL otherwise.
+**************************************************************************/
+static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+	IMG_UINT32 ui32SearchCriteria;
+	IMG_UINT32 ui32ResType;
+	IMG_PVOID pvParam;
+	IMG_UINT32 ui32Param;
+
+	ui32SearchCriteria = va_arg(va, IMG_UINT32);
+	ui32ResType = va_arg(va, IMG_UINT32);
+	pvParam = va_arg(va, IMG_PVOID);
+	ui32Param = va_arg(va, IMG_UINT32);
+
+	/*check that for all conditions are either disabled or eval to true*/
+	if(
+	/* Check resource type */
+		(((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+		(psCurItem->ui32ResType == ui32ResType))
+	&&
+	/* Check address */
+		(((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+			 (psCurItem->pvParam == pvParam))
+	&&
+	/* Check size */
+		(((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+			 (psCurItem->ui32Param == ui32Param))
+		)
+	{
+		return psCurItem;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+/*!
+******************************************************************************
+ @Function	 	FreeResourceByCriteria
+
+ @Description
+ 					Frees all resources that match the given criteria for the
+					context.
+					NOTE : this function must be called with the resource
+					list sync object held
+
+ @inputs        psResManContext - pointer to resman context
+ @inputs        ui32SearchCriteria - indicates which parameters should be used
+ @inputs        search for resources to free
+ @inputs        ui32ResType - identify what kind of resource to free
+ @inputs        pvParam - address of resource to be free
+ @inputs        ui32Param - size of resource to be free
+ @inputs        ui32AutoFreeLev - auto free level to free
+ @inputs        bExecuteCallback - execute callback?
+
+ @Return   		PVRSRV_ERROR
+**************************************************************************/
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT	psResManContext,
+										   IMG_UINT32		ui32SearchCriteria,
+										   IMG_UINT32		ui32ResType,
+										   IMG_PVOID		pvParam,
+										   IMG_UINT32		ui32Param,
+										   IMG_BOOL			bExecuteCallback)
+{
+	PRESMAN_ITEM	psCurItem;
+	PVRSRV_ERROR	eError = PVRSRV_OK;
+
+	/* Search resource items starting at after the first dummy item */
+	/*while we get a match and not an error*/
+	while((psCurItem = (PRESMAN_ITEM)
+				List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+										&FreeResourceByCriteria_AnyVaCb,
+										ui32SearchCriteria,
+										ui32ResType,
+						 				pvParam,
+						 				ui32Param)) != IMG_NULL
+		  	&& eError == PVRSRV_OK)
+	{
+		do
+		{
+			eError = FreeResourceByPtr(psCurItem, bExecuteCallback, CLEANUP_WITH_POLL);
+			if (eError == PVRSRV_ERROR_RETRY)
+			{
+				RELEASE_SYNC_OBJ;
+				OSReleaseBridgeLock();
+				/* Give a chance for other threads to come in and SGX to do more work */
+				OSSleepms(MAX_CLEANUP_TIME_WAIT_US/1000);
+				OSReacquireBridgeLock();
+				ACQUIRE_SYNC_OBJ;
+			}
+		} while (eError == PVRSRV_ERROR_RETRY);
+	}
+
+	return eError;
+}
+
+
+#ifdef DEBUG
+/*!
+******************************************************************************
+ @Function	 	ValidateResList
+
+ @Description
+ 					Walks the resource list check the pointers
+					NOTE : this function must be called with the resource
+					list sync object held
+
+ @Return   		none
+**************************************************************************/
+static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
+{
+	PRESMAN_ITEM	psCurItem, *ppsThisItem;
+	PRESMAN_CONTEXT	psCurContext, *ppsThisContext;
+
+	/* check we're initialised */
+	if (psResList == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
+		return;
+	}
+
+	psCurContext = psResList->psContextList;
+	ppsThisContext = &psResList->psContextList;
+
+	/* Walk the context list */
+	while(psCurContext != IMG_NULL)
+	{
+		/* Check current item */
+		PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+		if (psCurContext->ppsThis != ppsThisContext)
+		{
+			PVR_DPF((PVR_DBG_WARNING,
+					"psCC=%p psCC->ppsThis=%p psCC->psNext=%p ppsTC=%p",
+					psCurContext,
+					psCurContext->ppsThis,
+					psCurContext->psNext,
+					ppsThisContext));
+			PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+		}
+
+		/* Walk the list for this context */
+		psCurItem = psCurContext->psResItemList;
+		ppsThisItem = &psCurContext->psResItemList;
+		while(psCurItem != IMG_NULL)
+		{
+			/* Check current item */
+			PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
+			if (psCurItem->ppsThis != ppsThisItem)
+			{
+				PVR_DPF((PVR_DBG_WARNING,
+						"psCurItem=%p psCurItem->ppsThis=%p psCurItem->psNext=%p ppsThisItem=%p",
+						psCurItem,
+						psCurItem->ppsThis,
+						psCurItem->psNext,
+						ppsThisItem));
+				PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+			}
+
+			/* Move to next item */
+			ppsThisItem = &psCurItem->psNext;
+			psCurItem = psCurItem->psNext;
+		}
+
+		/* Move to next context */
+		ppsThisContext = &psCurContext->psNext;
+		psCurContext = psCurContext->psNext;
+	}
+}
+#endif /* DEBUG */
+
+
+/******************************************************************************
+ End of file (resman.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/common/ttrace.c b/drivers/gpu/pvr/services4/srvkm/common/ttrace.c
new file mode 100644
index 0000000..d1dd788
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/common/ttrace.c
@@ -0,0 +1,601 @@
+/*************************************************************************/ /*!
+@Title          Timed Trace functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if defined (TTRACE)
+
+#include "services_headers.h"
+#include "ttrace.h"
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+#define CHECKSIZE(n,m) \
+	if ((n & m) != n) \
+		PVR_DPF((PVR_DBG_ERROR,"Size check failed for " #m))
+#else
+#define CHECKSIZE(n,m)
+#endif
+
+#define TIME_TRACE_HASH_TABLE_SIZE	32
+
+HASH_TABLE *g_psBufferTable;
+IMG_UINT32 g_ui32HostUID;
+IMG_HANDLE g_psTimer;
+
+/* Trace buffer struct */
+typedef struct
+{
+	IMG_UINT32	ui32Woff;	/* Offset to where next item will be written */
+	IMG_UINT32	ui32Roff;	/* Offset to where to start reading from */
+	IMG_UINT32	ui32ByteCount;	/* Number of bytes in buffer */
+	IMG_UINT8	ui8Data[0];
+} sTimeTraceBuffer;
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceItemSize
+
+ @Description
+
+ Calculate the size of a trace item
+
+ @Input psTraceItem :	Trace item
+
+ @Return size of trace item
+
+******************************************************************************/
+static IMG_UINT32
+PVRSRVTimeTraceItemSize(IMG_UINT32 *psTraceItem)
+{
+	IMG_UINT32 ui32Size = PVRSRV_TRACE_ITEM_SIZE;
+
+	ui32Size += READ_HEADER(SIZE, psTraceItem[PVRSRV_TRACE_DATA_HEADER]);
+
+	return ui32Size;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceAllocItem
+
+ @Description
+
+ Allocate a trace item from the buffer of the current process
+
+ @Output ppsTraceItem :	Pointer to allocated trace item
+
+ @Input ui32Size : Size of data packet to be allocated
+
+ @Return none
+
+******************************************************************************/
+static IMG_VOID
+PVRSRVTimeTraceAllocItem(IMG_UINT32 **pui32Item, IMG_UINT32 ui32Size)
+{
+	IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+	IMG_UINT32 ui32AllocOffset;
+	sTimeTraceBuffer *psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID);
+
+	/* The caller only asks for extra data space */
+	ui32Size += PVRSRV_TRACE_ITEM_SIZE;
+
+	/* Always round to 32-bit */
+	ui32Size = ((ui32Size - 1) & (~0x3)) + 0x04;
+
+	if (!psBuffer)
+	{
+		PVRSRV_ERROR eError;
+
+		PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVTimeTraceAllocItem: Creating buffer for PID %u", ui32PID));
+		eError = PVRSRVTimeTraceBufferCreate(ui32PID);
+		if (eError != PVRSRV_OK)
+		{
+			*pui32Item = IMG_NULL;
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceAllocItem: Failed to create buffer"));
+			return;
+		}
+		
+		psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID);
+		if (psBuffer == IMG_NULL)
+		{
+			*pui32Item = NULL;
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceAllocItem: Failed to retrieve buffer"));
+			return;
+		}
+	}
+
+	/* Can't allocate more then buffer size */
+	if (ui32Size >= TIME_TRACE_BUFFER_SIZE)
+	{
+		*pui32Item = NULL;
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceAllocItem: Error trace item too large (%d)", ui32Size));
+		return;
+	}
+
+	/* FIXME: Enter critical section? */
+
+	/* Always ensure we have enough space to write a padding message */
+	if ((psBuffer->ui32Woff + ui32Size + PVRSRV_TRACE_ITEM_SIZE) > TIME_TRACE_BUFFER_SIZE)
+	{
+		IMG_UINT32 *ui32WriteEOB = (IMG_UINT32 *) &psBuffer->ui8Data[psBuffer->ui32Woff];
+		IMG_UINT32 ui32Remain = TIME_TRACE_BUFFER_SIZE - psBuffer->ui32Woff;
+
+		/* Not enough space at the end of the buffer, back to the start */
+		*ui32WriteEOB++ = WRITE_HEADER(GROUP, PVRSRV_TRACE_GROUP_PADDING);
+		*ui32WriteEOB++ = 0;		/* Don't need timestamp */
+		*ui32WriteEOB++ = 0;		/* Don't need UID */
+		*ui32WriteEOB = WRITE_HEADER(SIZE, (ui32Remain - PVRSRV_TRACE_ITEM_SIZE));
+		psBuffer->ui32ByteCount += ui32Remain;
+		psBuffer->ui32Woff = ui32AllocOffset = 0;
+	}
+	else
+		ui32AllocOffset = psBuffer->ui32Woff;
+
+	psBuffer->ui32Woff = psBuffer->ui32Woff + ui32Size;
+	psBuffer->ui32ByteCount += ui32Size;
+
+	/* This allocation will start overwriting past our read pointer, move the read pointer along */
+	while (psBuffer->ui32ByteCount > TIME_TRACE_BUFFER_SIZE)
+	{
+		IMG_UINT32 *psReadItem = (IMG_UINT32 *) &psBuffer->ui8Data[psBuffer->ui32Roff];
+		IMG_UINT32 ui32ReadSize;
+
+		ui32ReadSize = PVRSRVTimeTraceItemSize(psReadItem);
+		psBuffer->ui32Roff = (psBuffer->ui32Roff + ui32ReadSize) & (TIME_TRACE_BUFFER_SIZE - 1);
+		psBuffer->ui32ByteCount -= ui32ReadSize;
+	}
+
+	*pui32Item = (IMG_UINT32 *) &psBuffer->ui8Data[ui32AllocOffset];
+	/* FIXME: Exit critical section? */
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceBufferCreate
+
+ @Description
+
+ Create a trace buffer.
+
+ Note: We assume that this will only be called once per process.
+
+ @Input ui32PID : PID of the process that is creating the buffer
+
+ @Return none
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVTimeTraceBufferCreate(IMG_UINT32 ui32PID)
+{
+	sTimeTraceBuffer *psBuffer;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+					sizeof(sTimeTraceBuffer) + TIME_TRACE_BUFFER_SIZE,
+					(IMG_VOID **)&psBuffer, IMG_NULL,
+					"Time Trace Buffer");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferCreate: Error allocating trace buffer"));
+		return eError;
+	}
+
+	OSMemSet(psBuffer, 0, TIME_TRACE_BUFFER_SIZE);
+
+	if (!HASH_Insert(g_psBufferTable, (IMG_UINTPTR_T) ui32PID, (IMG_UINTPTR_T) psBuffer))
+	{
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer) + TIME_TRACE_BUFFER_SIZE,
+				psBuffer, NULL);
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferCreate: Error adding trace buffer to hash table"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceBufferDestroy
+
+ @Description
+
+ Destroy a trace buffer.
+
+ Note: We assume that this will only be called once per process.
+
+ @Input ui32PID : PID of the process that is creating the buffer
+
+ @Return none
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID)
+{
+#if !defined(TTRACE_KEEP_BUFFER_ON_EXIT)
+	sTimeTraceBuffer *psBuffer;
+
+#if defined(DUMP_TTRACE_BUFFERS_ON_EXIT)
+	PVRSRVDumpTimeTraceBuffers();
+#endif
+	psBuffer = (sTimeTraceBuffer *) HASH_Retrieve(g_psBufferTable, (IMG_UINTPTR_T) ui32PID);
+	if (psBuffer)
+	{
+		OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer) + TIME_TRACE_BUFFER_SIZE,
+				psBuffer, NULL);
+		HASH_Remove(g_psBufferTable, (IMG_UINTPTR_T) ui32PID);
+		return PVRSRV_OK;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferDestroy: Can't find trace buffer in hash table"));
+	return PVRSRV_ERROR_INVALID_PARAMS;
+#else
+	return PVRSRV_OK;
+#endif
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceInit
+
+ @Description
+
+ Initialise the timed trace subsystem.
+
+ @Return Error
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVTimeTraceInit(IMG_VOID)
+{
+	g_psBufferTable = HASH_Create(TIME_TRACE_HASH_TABLE_SIZE);
+
+	/* Create hash table to store the per process buffers in */
+	if (!g_psBufferTable)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceInit: Error creating hash table"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Create the kernel buffer */
+	PVRSRVTimeTraceBufferCreate(KERNEL_ID);
+
+	g_psTimer = OSFuncHighResTimerCreate();
+
+	if (!g_psTimer)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceInit: Error creating timer"));
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+	return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _PVRSRVTimeTraceBufferDestroy(IMG_UINTPTR_T hKey, IMG_UINTPTR_T hData)
+{
+	PVR_UNREFERENCED_PARAMETER(hData);
+	PVR_DPF((PVR_DBG_MESSAGE, "_PVRSRVTimeTraceBufferDestroy: Destroying buffer for PID %u", (IMG_UINT32) hKey));
+
+	PVRSRVTimeTraceBufferDestroy(hKey);
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceDeinit
+
+ @Description
+
+  De-initialise the timed trace subsystem.
+
+ @Return Error
+
+******************************************************************************/
+IMG_VOID PVRSRVTimeTraceDeinit(IMG_VOID)
+{
+	PVRSRVTimeTraceBufferDestroy(KERNEL_ID);
+	/* Free any buffers the where created at alloc item time */
+	HASH_Iterate(g_psBufferTable, _PVRSRVTimeTraceBufferDestroy);
+	HASH_Delete(g_psBufferTable);
+	OSFuncHighResTimerDestroy(g_psTimer);
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceWriteHeader
+
+ @Description
+
+ Write the header for a trace item.
+
+ @Input pui32TraceItem : Pointer to trace item
+
+ @Input ui32Group : Trace item's group ID
+
+ @Input ui32Class : Trace item's class ID
+
+ @Input ui32Token : Trace item's ui32Token ID
+
+ @Input ui32Size : Trace item's data payload size
+
+ @Input ui32Type : Trace item's data type
+
+ @Input ui32Count : Trace item's data count
+
+ @Return Pointer to data payload space, or NULL if no data payload
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceWriteHeader)
+#endif
+static INLINE IMG_VOID *PVRSRVTimeTraceWriteHeader(IMG_UINT32 *pui32TraceItem, IMG_UINT32 ui32Group,
+							IMG_UINT32 ui32Class, IMG_UINT32 ui32Token,
+							IMG_UINT32 ui32Size, IMG_UINT32 ui32Type,
+							IMG_UINT32 ui32Count)
+{
+	/* Sanity check arg's */
+	CHECKSIZE(ui32Group, PVRSRV_TRACE_GROUP_MASK);
+	CHECKSIZE(ui32Class, PVRSRV_TRACE_CLASS_MASK);
+	CHECKSIZE(ui32Token, PVRSRV_TRACE_TOKEN_MASK);
+
+	CHECKSIZE(ui32Size, PVRSRV_TRACE_SIZE_MASK);
+	CHECKSIZE(ui32Type, PVRSRV_TRACE_TYPE_MASK);
+	CHECKSIZE(ui32Count, PVRSRV_TRACE_COUNT_MASK);
+
+	/* Trace header */
+	pui32TraceItem[PVRSRV_TRACE_HEADER] = WRITE_HEADER(GROUP, ui32Group);
+	pui32TraceItem[PVRSRV_TRACE_HEADER] |= WRITE_HEADER(CLASS, ui32Class);
+	pui32TraceItem[PVRSRV_TRACE_HEADER] |= WRITE_HEADER(TOKEN, ui32Token);
+
+	/* Data header */
+	pui32TraceItem[PVRSRV_TRACE_DATA_HEADER] = WRITE_HEADER(SIZE, ui32Size);
+	pui32TraceItem[PVRSRV_TRACE_DATA_HEADER] |= WRITE_HEADER(TYPE, ui32Type);
+	pui32TraceItem[PVRSRV_TRACE_DATA_HEADER] |= WRITE_HEADER(COUNT, ui32Count);
+
+	pui32TraceItem[PVRSRV_TRACE_TIMESTAMP] = OSFuncHighResTimerGetus(g_psTimer);
+	pui32TraceItem[PVRSRV_TRACE_HOSTUID] = g_ui32HostUID++;
+
+	return ui32Size?((IMG_VOID *) &pui32TraceItem[PVRSRV_TRACE_DATA_PAYLOAD]):NULL;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceArray
+
+ @Description
+
+ Write trace item with an array of data
+
+ @Input ui32Group : Trace item's group ID
+
+ @Input ui32Class : Trace item's class ID
+
+ @Input ui32Token : Trace item's ui32Token ID
+
+ @Input ui32Size : Trace item's data payload size
+
+ @Input ui32Type : Trace item's data type
+
+ @Input ui32Count : Trace item's data count
+
+ @Input pui8Data : Pointer to data array
+
+ @Return Pointer to data payload space, or NULL if no data payload
+
+******************************************************************************/
+IMG_VOID PVRSRVTimeTraceArray(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class, IMG_UINT32 ui32Token,
+				IMG_UINT32 ui32Type, IMG_UINT32 ui32Count, IMG_UINT8 *pui8Data)
+{
+	IMG_UINT32 *pui32TraceItem;
+	IMG_UINT32 ui32Size, ui32TypeSize;
+	IMG_UINT8 *ui8Ptr;
+
+	/* Only the 1st 4 sizes are for ui types, others are "special" */
+	switch (ui32Type)
+	{
+		case PVRSRV_TRACE_TYPE_UI8:	ui32TypeSize = 1;
+						break;
+		case PVRSRV_TRACE_TYPE_UI16:	ui32TypeSize = 2;
+						break;
+		case PVRSRV_TRACE_TYPE_UI32:	ui32TypeSize = 4;
+						break;
+		case PVRSRV_TRACE_TYPE_UI64:	ui32TypeSize = 8;
+						break;
+		default:
+			PVR_DPF((PVR_DBG_ERROR, "Unsupported size\n"));
+			return;
+	}
+
+	ui32Size = ui32TypeSize * ui32Count;
+
+	/* Allocate space from the buffer */
+	PVRSRVTimeTraceAllocItem(&pui32TraceItem, ui32Size);
+
+	if (!pui32TraceItem)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Can't find buffer\n"));
+		return;
+	}
+
+	ui8Ptr = PVRSRVTimeTraceWriteHeader(pui32TraceItem, ui32Group, ui32Class, ui32Token,
+						ui32Size, ui32Type, ui32Count);
+
+	if (ui8Ptr)
+	{
+		OSMemCopy(ui8Ptr, pui8Data, ui32Size);
+	}
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVTimeTraceSyncObject
+
+ @Description
+
+ Write trace item with a sync object
+
+ @Input ui32Group : Trace item's group ID
+
+ @Input ui32Token : Trace item's ui32Token ID
+
+ @Input psSync : Sync object
+
+ @Input ui8SyncOpp : Sync object operation
+
+ @Return None
+
+******************************************************************************/
+IMG_VOID PVRSRVTimeTraceSyncObject(IMG_UINT32 ui32Group, IMG_UINT32 ui32Token,
+				   PVRSRV_KERNEL_SYNC_INFO *psSync, IMG_UINT8 ui8SyncOp)
+{
+	IMG_UINT32 *pui32TraceItem;
+	IMG_UINT32 *ui32Ptr;
+	IMG_UINT32 ui32Size = PVRSRV_TRACE_TYPE_SYNC_SIZE;
+
+
+	PVRSRVTimeTraceAllocItem(&pui32TraceItem, ui32Size);
+
+	if (!pui32TraceItem)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Can't find buffer\n"));
+		return;
+	}
+
+	ui32Ptr = PVRSRVTimeTraceWriteHeader(pui32TraceItem, ui32Group, PVRSRV_TRACE_CLASS_SYNC,
+						ui32Token, ui32Size, PVRSRV_TRACE_TYPE_SYNC, 1);
+
+	ui32Ptr[PVRSRV_TRACE_SYNC_UID] = psSync->ui32UID;
+	ui32Ptr[PVRSRV_TRACE_SYNC_WOP] = psSync->psSyncData->ui32WriteOpsPending;
+	ui32Ptr[PVRSRV_TRACE_SYNC_WOC] = psSync->psSyncData->ui32WriteOpsComplete;
+	ui32Ptr[PVRSRV_TRACE_SYNC_ROP] = psSync->psSyncData->ui32ReadOpsPending;
+	ui32Ptr[PVRSRV_TRACE_SYNC_ROC] = psSync->psSyncData->ui32ReadOpsComplete;
+	ui32Ptr[PVRSRV_TRACE_SYNC_RO2P] = psSync->psSyncData->ui32ReadOps2Pending;
+	ui32Ptr[PVRSRV_TRACE_SYNC_RO2C] = psSync->psSyncData->ui32ReadOps2Complete;
+	ui32Ptr[PVRSRV_TRACE_SYNC_WO_DEV_VADDR] = psSync->sWriteOpsCompleteDevVAddr.uiAddr;
+	ui32Ptr[PVRSRV_TRACE_SYNC_RO_DEV_VADDR] = psSync->sReadOpsCompleteDevVAddr.uiAddr;
+	ui32Ptr[PVRSRV_TRACE_SYNC_RO2_DEV_VADDR] = psSync->sReadOps2CompleteDevVAddr.uiAddr;
+	ui32Ptr[PVRSRV_TRACE_SYNC_OP] = ui8SyncOp;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDumpTimeTraceBuffer
+
+ @Description
+
+ Dump the contents of the trace buffer.
+
+ @Input hKey : Trace item's group ID
+
+ @Input hData : Trace item's ui32Token ID
+
+ @Return Error
+
+******************************************************************************/
+static PVRSRV_ERROR PVRSRVDumpTimeTraceBuffer(IMG_UINTPTR_T hKey, IMG_UINTPTR_T hData)
+{
+	sTimeTraceBuffer *psBuffer = (sTimeTraceBuffer *) hData;
+	IMG_UINT32 ui32ByteCount = psBuffer->ui32ByteCount;
+	IMG_UINT32 ui32Walker = psBuffer->ui32Roff;
+	IMG_UINT32 ui32Read, ui32LineLen, ui32EOL, ui32MinLine;
+
+	PVR_LOG(("TTB for PID %u:\n", (IMG_UINT32) hKey));
+
+	while (ui32ByteCount)
+	{
+		IMG_UINT32 *pui32Buffer = (IMG_UINT32 *) &psBuffer->ui8Data[ui32Walker];
+
+		ui32LineLen = (ui32ByteCount/sizeof(IMG_UINT32));
+		ui32EOL = (TIME_TRACE_BUFFER_SIZE - ui32Walker)/sizeof(IMG_UINT32);
+		ui32MinLine = (ui32LineLen < ui32EOL)?ui32LineLen:ui32EOL;
+
+		if (ui32MinLine >= 4)
+		{
+			PVR_LOG(("\t(TTB-%X) %08X %08X %08X %08X [", ui32ByteCount,
+					pui32Buffer[0], pui32Buffer[1], pui32Buffer[2], pui32Buffer[3]));
+			ui32Read = 4 * sizeof(IMG_UINT32);
+		}
+		else if (ui32MinLine >= 3)
+		{
+			PVR_LOG(("\t(TTB-%X) %08X %08X %08X [", ui32ByteCount,
+					pui32Buffer[0], pui32Buffer[1], pui32Buffer[2]));
+			ui32Read = 3 * sizeof(IMG_UINT32);
+		}
+		else if (ui32MinLine >= 2)
+		{
+			PVR_LOG(("\t(TTB-%X) %08X %08X [", ui32ByteCount,
+					pui32Buffer[0], pui32Buffer[1]));
+			ui32Read = 2 * sizeof(IMG_UINT32);
+		}
+		else
+		{
+			PVR_LOG(("\t(TTB-%X) %08X [", ui32ByteCount,
+					pui32Buffer[0]));
+			ui32Read = sizeof(IMG_UINT32);
+		}
+
+		ui32Walker = (ui32Walker + ui32Read) & (TIME_TRACE_BUFFER_SIZE - 1);
+		ui32ByteCount -= ui32Read;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	PVRSRVDumpTimeTraceBuffers
+
+ @Description
+
+ Dump the contents of all the trace buffers.
+
+ @Return None
+
+******************************************************************************/
+IMG_VOID PVRSRVDumpTimeTraceBuffers(IMG_VOID)
+{
+	HASH_Iterate(g_psBufferTable, PVRSRVDumpTimeTraceBuffer);
+}
+
+#endif /* TTRACE */
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/mmu.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/mmu.c
new file mode 100644
index 0000000..774d151
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/mmu.c
@@ -0,0 +1,4734 @@
+/*************************************************************************/ /*!
+@Title          MMU Management
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements basic low level control of MMU.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "mmu.h"
+#include "sgxconfig.h"
+#include "sgx_bridge_km.h"
+#include "pdump_osfunc.h"
+
+#define UINT32_MAX_VALUE	0xFFFFFFFFUL
+
+/*
+	MMU performs device virtual to physical translation.
+	terminology:
+	page directory (PD)
+	pagetable (PT)
+	data page (DP)
+
+	Incoming 32bit Device Virtual Addresses are deconstructed into 3 fields:
+	---------------------------------------------------------
+	|	PD Index/tag:	|	PT Index:	|	DP offset:		|
+	|	bits 31:22		|	bits 21:n	|	bits (n-1):0	|
+	---------------------------------------------------------
+		where typically n=12 for a standard 4k DP
+		but n=16 for a 64k DP
+
+	MMU page directory (PD), pagetable (PT) and data page (DP) config:
+	PD:
+	- always one page per address space
+	- up to 4k in size to span 4Gb (32bit)
+	- contains up to 1024 32bit entries
+	- entries are indexed by the top 12 bits of an incoming 32bit device virtual address
+	- the PD entry selected contains the physical address of the PT to
+	  perform the next stage of the V to P translation
+
+	PT:
+	- size depends on the DP size, e.g. 4k DPs have 4k PTs but 16k DPs have 1k PTs
+	- each PT always spans 4Mb of device virtual address space irrespective of DP size
+	- number of entries in a PT depend on DP size and ranges from 1024 to 4 entries
+	- entries are indexed by the PT Index field of the device virtual address (21:n)
+	- the PT entry selected contains the physical address of the DP to access
+
+	DP:
+	- size varies from 4k to 4M in multiple of 4 steppings
+	- DP offset field of the device virtual address ((n-1):0) is used as a byte offset
+	  to address into the DP itself
+*/
+
+#define SGX_MAX_PD_ENTRIES	(1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
+
+#if defined(FIX_HW_BRN_31620)
+/* Sim doesn't use the address mask */
+#define SGX_MMU_PDE_DUMMY_PAGE		(0)//(0x00000020U)
+#define SGX_MMU_PTE_DUMMY_PAGE		(0)//(0x00000020U)
+
+/* 4MB adress range per page table */
+#define BRN31620_PT_ADDRESS_RANGE_SHIFT		22
+#define BRN31620_PT_ADDRESS_RANGE_SIZE		(1 << BRN31620_PT_ADDRESS_RANGE_SHIFT)
+
+/* 64MB address range per PDE cache line */
+#define BRN31620_PDE_CACHE_FILL_SHIFT		26
+#define BRN31620_PDE_CACHE_FILL_SIZE		(1 << BRN31620_PDE_CACHE_FILL_SHIFT)
+#define BRN31620_PDE_CACHE_FILL_MASK		(BRN31620_PDE_CACHE_FILL_SIZE - 1)
+
+/* Page Directory Enteries per cache line */
+#define BRN31620_PDES_PER_CACHE_LINE_SHIFT	(BRN31620_PDE_CACHE_FILL_SHIFT - BRN31620_PT_ADDRESS_RANGE_SHIFT)
+#define BRN31620_PDES_PER_CACHE_LINE_SIZE	(1 << BRN31620_PDES_PER_CACHE_LINE_SHIFT)
+#define BRN31620_PDES_PER_CACHE_LINE_MASK	(BRN31620_PDES_PER_CACHE_LINE_SIZE - 1)
+
+/* Macros for working out offset for dummy pages */
+#define BRN31620_DUMMY_PAGE_OFFSET	(1 * SGX_MMU_PAGE_SIZE)
+#define BRN31620_DUMMY_PDE_INDEX	(BRN31620_DUMMY_PAGE_OFFSET / BRN31620_PT_ADDRESS_RANGE_SIZE)
+#define BRN31620_DUMMY_PTE_INDEX	((BRN31620_DUMMY_PAGE_OFFSET - (BRN31620_DUMMY_PDE_INDEX * BRN31620_PT_ADDRESS_RANGE_SIZE))/SGX_MMU_PAGE_SIZE)
+
+/* Cache number of cache lines */
+#define BRN31620_CACHE_FLUSH_SHIFT		(32 - BRN31620_PDE_CACHE_FILL_SHIFT)
+#define BRN31620_CACHE_FLUSH_SIZE		(1 << BRN31620_CACHE_FLUSH_SHIFT)
+
+/* Cache line bits in a UINT32 */
+#define BRN31620_CACHE_FLUSH_BITS_SHIFT		5
+#define BRN31620_CACHE_FLUSH_BITS_SIZE		(1 << BRN31620_CACHE_FLUSH_BITS_SHIFT)
+#define BRN31620_CACHE_FLUSH_BITS_MASK		(BRN31620_CACHE_FLUSH_BITS_SIZE - 1)
+
+/* Cache line index in array */
+#define BRN31620_CACHE_FLUSH_INDEX_BITS		(BRN31620_CACHE_FLUSH_SHIFT - BRN31620_CACHE_FLUSH_BITS_SHIFT)
+#define BRN31620_CACHE_FLUSH_INDEX_SIZE		(1 << BRN31620_CACHE_FLUSH_INDEX_BITS)
+
+#define BRN31620_DUMMY_PAGE_SIGNATURE	0xFEEBEE01
+#endif
+
+typedef struct _MMU_PT_INFO_
+{
+	/* note: may need a union here to accommodate a PT page address for local memory */
+	IMG_VOID *hPTPageOSMemHandle;
+	IMG_CPU_VIRTADDR PTPageCpuVAddr;
+	/* Map of reserved PTEs.
+	 * Reserved PTEs are like "valid" PTEs in that they (and the DevVAddrs they represent)
+	 * cannot be assigned to another allocation but their "reserved" status persists through
+	 * any amount of mapping and unmapping, until the allocation is finally destroyed.
+	 *
+	 * Reserved and Valid are independent.
+	 * When a PTE is first reserved, it will have Reserved=1 and Valid=0.
+	 * When the PTE is actually mapped, it will have Reserved=1 and Valid=1.
+	 * When the PTE is unmapped, it will have Reserved=1 and Valid=0.
+	 * At this point, the PT will can not be destroyed because although there is
+	 * not an active mapping on the PT, it is known a PTE is reserved for use.
+	 *
+	 * The above sequence of mapping and unmapping may repeat any number of times
+	 * until the allocation is unmapped and destroyed which causes the PTE to have
+	 * Valid=0 and Reserved=0.
+	 */
+	/* Number of PTEs set up.
+	 * i.e. have a valid SGX Phys Addr and the "VALID" PTE bit == 1
+	 */
+	IMG_UINT32 ui32ValidPTECount;
+} MMU_PT_INFO;
+
+#define MMU_CONTEXT_NAME_SIZE	50
+struct _MMU_CONTEXT_
+{
+	/* the device node */
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	/* Page Directory CPUVirt and DevPhys Addresses */
+	IMG_CPU_VIRTADDR pvPDCpuVAddr;
+	IMG_DEV_PHYADDR sPDDevPAddr;
+
+	IMG_VOID *hPDOSMemHandle;
+
+	/* information about dynamically allocated pagetables */
+	MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
+
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+
+#if defined(PDUMP)
+	IMG_UINT32 ui32PDumpMMUContextID;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	IMG_BOOL bPDumpActive;
+#endif
+#endif
+
+	IMG_UINT32 ui32PID;
+	IMG_CHAR szName[MMU_CONTEXT_NAME_SIZE];
+
+#if defined (FIX_HW_BRN_31620)
+	IMG_UINT32 ui32PDChangeMask[BRN31620_CACHE_FLUSH_INDEX_SIZE];
+	IMG_UINT32 ui32PDCacheRangeRefCount[BRN31620_CACHE_FLUSH_SIZE];
+	MMU_PT_INFO *apsPTInfoListSave[SGX_MAX_PD_ENTRIES];
+#endif
+	struct _MMU_CONTEXT_ *psNext;
+};
+
+struct _MMU_HEAP_
+{
+	/* MMU context */
+	MMU_CONTEXT			*psMMUContext;
+
+	/*
+		heap specific details:
+	*/
+	/* the Base PD index for the heap */
+	IMG_UINT32			ui32PDBaseIndex;
+	/* number of pagetables in this heap */
+	IMG_UINT32			ui32PageTableCount;
+	/* total number of pagetable entries in this heap which may be mapped to data pages */
+	IMG_UINT32			ui32PTETotalUsable;
+	/* PD entry DP size control field */
+	IMG_UINT32			ui32PDEPageSizeCtrl;
+
+	/*
+		Data Page (DP) Details:
+	*/
+	/* size in bytes of a data page */
+	IMG_UINT32			ui32DataPageSize;
+	/* bit width of the data page offset addressing field */
+	IMG_UINT32			ui32DataPageBitWidth;
+	/* bit mask of the data page offset addressing field */
+	IMG_UINT32			ui32DataPageMask;
+
+	/*
+		PageTable (PT) Details:
+	*/
+	/* bit shift to base of PT addressing field */
+	IMG_UINT32			ui32PTShift;
+	/* bit width of the PT addressing field */
+	IMG_UINT32			ui32PTBitWidth;
+	/* bit mask of the PT addressing field */
+	IMG_UINT32			ui32PTMask;
+	/* size in bytes of a pagetable */
+	IMG_UINT32			ui32PTSize;
+	/* Allocated PT Entries per PT */
+	IMG_UINT32			ui32PTNumEntriesAllocated;
+	/* Usable PT Entries per PT (may be different to num allocated for 4MB data page) */
+	IMG_UINT32			ui32PTNumEntriesUsable;
+
+	/*
+		PageDirectory Details:
+	*/
+	/* bit shift to base of PD addressing field */
+	IMG_UINT32			ui32PDShift;
+	/* bit width of the PD addressing field */
+	IMG_UINT32			ui32PDBitWidth;
+	/* bit mask of the PT addressing field */
+	IMG_UINT32			ui32PDMask;
+
+	/*
+		Arena Info:
+	*/
+	RA_ARENA *psVMArena;
+	DEV_ARENA_DESCRIPTOR *psDevArena;
+
+	/* If we have sparse mappings then we can't do PT level sanity checks */
+	IMG_BOOL bHasSparseMappings;
+#if defined(PDUMP)
+	PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+};
+
+
+
+#if defined (SUPPORT_SGX_MMU_DUMMY_PAGE)
+#define DUMMY_DATA_PAGE_SIGNATURE	0xDEADBEEF
+#endif
+
+/* local prototypes: */
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT);
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+IMG_IMPORT IMG_VOID PVRSRVPrintMemTrackInfo(IMG_UINT32 ui32FaultAddr);
+#endif
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables	(MMU_HEAP *pMMUHeap,
+					 IMG_DEV_VIRTADDR DevVAddr,
+					 IMG_SIZE_T uSize,
+					 IMG_BOOL bForUnmap,
+					 IMG_HANDLE hUniqueTag);
+#endif /* #if defined(PDUMP) */
+
+/* This option tests page table memory, for use during device bring-up. */
+#define PAGE_TEST					0
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
+#endif
+
+/* This option dumps out the PT if an assert fails */
+#define PT_DUMP 1
+
+/* This option sanity checks page table PTE valid count matches active PTEs */
+#define PT_DEBUG 0
+#if (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF)
+static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+	IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+	IMG_UINT32 i;
+
+	/* 1024 entries in a 4K page table */
+	for(i = 0; i < 1024; i += 8)
+	{
+		PVR_LOG(("%08X %08X %08X %08X %08X %08X %08X %08X",
+				 p[i + 0], p[i + 1], p[i + 2], p[i + 3],
+				 p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
+	}
+}
+#else /* (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF) */
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+	PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif /* (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF) */
+
+#if PT_DEBUG
+static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+	IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
+	IMG_UINT32 i, ui32Count = 0;
+
+	/* 1024 entries in a 4K page table */
+	for(i = 0; i < 1024; i++)
+		if(p[i] & SGX_MMU_PTE_VALID)
+			ui32Count++;
+
+	if(psPTInfoList->ui32ValidPTECount != ui32Count)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "ui32ValidPTECount: %u ui32Count: %u",
+				 psPTInfoList->ui32ValidPTECount, ui32Count));
+		DumpPT(psPTInfoList);
+		PVR_DBG_BREAK;
+	}
+}
+#else /* PT_DEBUG */
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+	PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif /* PT_DEBUG */
+
+/*
+	Debug functionality that allows us to make the CPU
+	mapping of pagetable memory readonly and only make
+	it read/write when we alter it. This allows us
+	to check that our memory isn't being overwritten
+*/
+#if defined(__linux__) && defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND)
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#else
+#include <generated/autoconf.h>
+#endif
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+static IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
+{
+    pgd_t *psPGD;
+    pud_t *psPUD;
+    pmd_t *psPMD;
+    pte_t *psPTE;
+    pte_t ptent;
+    IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+
+    psPGD = pgd_offset_k(ui32CPUVAddr);
+    if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+    {
+        PVR_ASSERT(0);
+    }
+
+    psPUD = pud_offset(psPGD, ui32CPUVAddr);
+    if (pud_none(*psPUD) || pud_bad(*psPUD))
+    {
+        PVR_ASSERT(0);
+    }
+
+    psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+    if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+    {
+        PVR_ASSERT(0);
+    }
+	psPTE = (pte_t *)pte_offset_kernel(psPMD, ui32CPUVAddr);
+
+	ptent = ptep_modify_prot_start(&init_mm, ui32CPUVAddr, psPTE);
+	ptent = pte_mkwrite(ptent);
+	ptep_modify_prot_commit(&init_mm, ui32CPUVAddr, psPTE, ptent);
+
+	flush_tlb_all();
+}
+
+static IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+    pgd_t *psPGD;
+    pud_t *psPUD;
+    pmd_t *psPMD;
+    pte_t *psPTE;
+    pte_t ptent;
+    IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+
+	OSWriteMemoryBarrier();
+
+    psPGD = pgd_offset_k(ui32CPUVAddr);
+    if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+    {
+        PVR_ASSERT(0);
+    }
+
+    psPUD = pud_offset(psPGD, ui32CPUVAddr);
+    if (pud_none(*psPUD) || pud_bad(*psPUD))
+    {
+        PVR_ASSERT(0);
+    }
+
+    psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+    if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+    {
+        PVR_ASSERT(0);
+    }
+
+	psPTE = (pte_t *)pte_offset_kernel(psPMD, ui32CPUVAddr);
+
+	ptent = ptep_modify_prot_start(&init_mm, ui32CPUVAddr, psPTE);
+	ptent = pte_wrprotect(ptent);
+	ptep_modify_prot_commit(&init_mm, ui32CPUVAddr, psPTE, ptent);
+
+	flush_tlb_all();
+
+}
+
+#else /* defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND) */
+
+static INLINE IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
+{
+	PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
+}
+
+static INLINE IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+	PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
+}
+
+#endif /* defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND) */
+
+/*___________________________________________________________________________
+
+	Information for SUPPORT_PDUMP_MULTI_PROCESS feature.
+	
+	The client marked for pdumping will set the bPDumpActive flag in
+	the MMU Context (see MMU_Initialise).
+	
+	Shared heap allocations should be persistent so all apps which
+	are pdumped will see the allocation. Persistent flag over-rides
+	the bPDumpActive flag (see pdump_common.c/DbgWrite function).
+	
+	The idea is to dump PT,DP for shared heap allocations, but only
+	dump the PDE if the allocation is mapped into the kernel or active
+	client context. This ensures if a background app allocates on a
+	shared heap then all clients can access it in the pdump toolchain.
+	
+	
+	
+	PD		PT		DP
+	+-+
+	| |--->	+-+
+	+-+		| |--->	+-+
+			+-+		+ +
+					+-+
+					
+	PD allocation/free: pdump flags are 0 (only need PD for active apps)
+	PT allocation/free: pdump flags are 0
+						unless PT is for a shared heap, in which case persistent is set
+	PD entries (MMU init/insert shared heap):
+						only pdump if PDE is on the active MMU context, flags are 0
+	PD entries (PT alloc):
+						pdump flags are 0 if kernel heap
+						pdump flags are 0 if shared heap and PDE is on active MMU context
+						otherwise ignore.
+	PT entries			pdump flags are 0
+						unless PTE is for a shared heap, in which case persistent is set
+						
+	NOTE: PDump common code:-
+	PDumpMallocPages and PDumpMemKM also set the persistent flag for
+	shared heap allocations.
+	
+  ___________________________________________________________________________
+*/
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_IsHeapShared
+
+	PURPOSE:    Is this heap shared?
+	PARAMETERS: In: pMMU_Heap
+	RETURNS:    true if heap is shared
+******************************************************************************/
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap)
+{
+	switch(pMMUHeap->psDevArena->DevMemHeapType)
+	{
+		case DEVICE_MEMORY_HEAP_SHARED :
+		case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+			return IMG_TRUE;
+		case DEVICE_MEMORY_HEAP_PERCONTEXT :
+		case DEVICE_MEMORY_HEAP_KERNEL :
+			return IMG_FALSE;
+		default:
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_IsHeapShared: ERROR invalid heap type"));
+			return IMG_FALSE;
+		}
+	}
+}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+/*!
+******************************************************************************
+	FUNCTION:   EnableHostAccess
+
+	PURPOSE:    Enables Host accesses to device memory, by passing the device
+				MMU address translation
+
+	PARAMETERS: In: psMMUContext
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+	IMG_UINT32 ui32RegVal;
+	IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+	/*
+		bypass the MMU for the host port requestor,
+		conserving bypass state of other requestors
+	*/
+	ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
+
+	OSWriteHWReg(pvRegsBaseKM,
+				EUR_CR_BIF_CTRL,
+				ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+	/* assume we're not wiping-out any other bits */
+	PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   DisableHostAccess
+
+	PURPOSE:    Disables Host accesses to device memory, by passing the device
+				MMU address translation
+
+	PARAMETERS: In: psMMUContext
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+	IMG_UINT32 ui32RegVal;
+	IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+	/*
+		disable MMU-bypass for the host port requestor,
+		conserving bypass state of other requestors
+		and flushing all caches/tlbs
+	*/
+	OSWriteHWReg(pvRegsBaseKM,
+				EUR_CR_BIF_CTRL,
+				ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+	/* assume we're not wiping-out any other bits */
+	PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, 0);
+}
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+/*!
+******************************************************************************
+	FUNCTION:   MMU_InvalidateSystemLevelCache
+
+	PURPOSE:    Invalidates the System Level Cache to purge stale PDEs and PTEs
+
+	PARAMETERS: In: psDevInfo
+	RETURNS:    None
+
+******************************************************************************/
+static IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	#if defined(SGX_FEATURE_MP)
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+	#else
+	/* The MMU always bypasses the SLC */
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	#endif /* SGX_FEATURE_MP */
+}
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_InvalidateDirectoryCache
+
+	PURPOSE:    Invalidates the page directory cache + page table cache + requestor TLBs
+
+	PARAMETERS: In: psDevInfo
+	RETURNS:    None
+
+******************************************************************************/
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	MMU_InvalidateSystemLevelCache(psDevInfo);
+	#endif /* SGX_FEATURE_SYSTEM_CACHE */
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_InvalidatePageTableCache
+
+	PURPOSE:    Invalidates the page table cache + requestor TLBs
+
+	PARAMETERS: In: psDevInfo
+	RETURNS:    None
+
+******************************************************************************/
+static IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	MMU_InvalidateSystemLevelCache(psDevInfo);
+	#endif /* SGX_FEATURE_SYSTEM_CACHE */
+}
+
+#if defined(FIX_HW_BRN_31620)
+/*!
+******************************************************************************
+	FUNCTION:   BRN31620InvalidatePageTableEntry
+
+	PURPOSE:    Frees page tables in PDE cache line chunks re-wiring the
+	            dummy page when required
+
+	PARAMETERS: In: psMMUContext, ui32PDIndex, ui32PTIndex
+	RETURNS:    None
+
+******************************************************************************/
+static IMG_VOID BRN31620InvalidatePageTableEntry(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32PDIndex, IMG_UINT32 ui32PTIndex, IMG_UINT32 *pui32PTE)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
+
+	/*
+	 * Note: We can't tell at this stage if this PT will be freed before
+	 * the end of the function so we always wire up the dummy page to
+	 * to the PT.
+	 */
+	if (((ui32PDIndex % (BRN31620_PDE_CACHE_FILL_SIZE/BRN31620_PT_ADDRESS_RANGE_SIZE)) == BRN31620_DUMMY_PDE_INDEX)
+		&& (ui32PTIndex == BRN31620_DUMMY_PTE_INDEX))
+	{
+		*pui32PTE = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+								| SGX_MMU_PTE_DUMMY_PAGE
+								| SGX_MMU_PTE_READONLY
+								| SGX_MMU_PTE_VALID;
+	}
+	else
+	{
+		*pui32PTE = 0;
+	}
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   BRN31620FreePageTable
+
+	PURPOSE:    Frees page tables in PDE cache line chunks re-wiring the
+	            dummy page when required
+
+	PARAMETERS: In: psMMUContext, ui32PDIndex
+	RETURNS:    IMG_TRUE if we freed any PT's
+
+******************************************************************************/
+static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDIndex)
+{
+	MMU_CONTEXT *psMMUContext = psMMUHeap->psMMUContext;
+	PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
+	IMG_UINT32 ui32PDCacheLine = ui32PDIndex >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
+	IMG_UINT32 bFreePTs = IMG_FALSE;
+	IMG_UINT32 *pui32Tmp;
+
+	PVR_ASSERT(psMMUHeap != IMG_NULL);
+
+	/* 
+	 * Clear the PT info for this PD index so even if we don't
+	 * free the memory here apsPTInfoList[PDIndex] will trigger
+	 * an "allocation" in _DeferredAllocPagetables which
+	 * bumps up the refcount.
+	 */
+	PVR_ASSERT(psMMUContext->apsPTInfoListSave[ui32PDIndex] == IMG_NULL);
+
+	psMMUContext->apsPTInfoListSave[ui32PDIndex] = psMMUContext->apsPTInfoList[ui32PDIndex];
+	psMMUContext->apsPTInfoList[ui32PDIndex] = IMG_NULL;
+
+	/* Check if this was the last PT in the cache line */
+	if (--psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine] == 0)
+	{
+		IMG_UINT32 i;
+		IMG_UINT32 ui32PDIndexStart = ui32PDCacheLine * BRN31620_PDES_PER_CACHE_LINE_SIZE;
+		IMG_UINT32 ui32PDIndexEnd = ui32PDIndexStart + BRN31620_PDES_PER_CACHE_LINE_SIZE;
+		IMG_UINT32 ui32PDBitMaskIndex, ui32PDBitMaskShift;
+
+		/* Free all PT's in cache line */
+		for (i=ui32PDIndexStart;i<ui32PDIndexEnd;i++)
+		{
+			/* This PT is _really_ being freed now */
+			psMMUContext->apsPTInfoList[i] = psMMUContext->apsPTInfoListSave[i];
+			psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
+			_DeferredFreePageTable(psMMUHeap, i - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+		}
+
+		ui32PDBitMaskIndex = ui32PDCacheLine >> BRN31620_CACHE_FLUSH_BITS_SHIFT;
+		ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
+
+		/* Check if this is a shared heap */
+		if (MMU_IsHeapShared(psMMUHeap))
+		{
+			/* Mark the remove of the Page Table from all memory contexts */
+			MMU_CONTEXT *psMMUContextWalker = (MMU_CONTEXT*) psMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+			while(psMMUContextWalker)
+			{
+				psMMUContextWalker->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
+
+				/*
+				 * We've just cleared a cache line's worth of PDE's so we need
+				 * to wire up the dummy PT
+				 */
+				MakeKernelPageReadWrite(psMMUContextWalker->pvPDCpuVAddr);
+				pui32Tmp = (IMG_UINT32 *) psMMUContextWalker->pvPDCpuVAddr;
+				pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+												| SGX_MMU_PDE_PAGE_SIZE_4K
+												| SGX_MMU_PDE_DUMMY_PAGE
+												| SGX_MMU_PDE_VALID;
+				MakeKernelPageReadOnly(psMMUContextWalker->pvPDCpuVAddr);
+
+				PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
+				PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContextWalker->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+				psMMUContextWalker = psMMUContextWalker->psNext;
+			}
+		}
+		else
+		{
+			psMMUContext->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
+
+			/*
+			 * We've just cleared a cache line's worth of PDE's so we need
+			 * to wire up the dummy PT
+			 */
+			MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+			pui32Tmp = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+			pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+											| SGX_MMU_PDE_PAGE_SIZE_4K
+											| SGX_MMU_PDE_DUMMY_PAGE
+											| SGX_MMU_PDE_VALID;
+			MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+
+			PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
+			PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+		}
+		/* We've freed a cachline's worth of PDE's so trigger a PD cache flush */
+		bFreePTs = IMG_TRUE;
+	}
+
+	return bFreePTs;
+}
+#endif
+
+/*!
+******************************************************************************
+	FUNCTION:   _AllocPageTableMemory
+
+	PURPOSE:    Allocate physical memory for a page table
+
+	PARAMETERS: In: pMMUHeap - the mmu
+				In: psPTInfoList - PT info
+				Out: psDevPAddr - device physical address for new PT
+	RETURNS:    IMG_TRUE - Success
+	            IMG_FALSE - Failed
+******************************************************************************/
+static IMG_BOOL
+_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
+						MMU_PT_INFO *psPTInfoList,
+						IMG_DEV_PHYADDR	*psDevPAddr)
+{
+	IMG_DEV_PHYADDR	sDevPAddr;
+	IMG_CPU_PHYADDR sCpuPAddr;
+
+	/*
+		depending on the specific system, pagetables are allocated from system memory
+		or device local memory.  For now, just look for at least a valid local heap/arena
+	*/
+	if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+	{
+		//FIXME: replace with an RA, this allocator only handles 4k allocs
+		if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						 pMMUHeap->ui32PTSize,
+						 SGX_MMU_PAGE_SIZE,//FIXME: assume 4K page size for now (wastes memory for smaller pagetables
+						 IMG_NULL,
+						 0,
+						 IMG_NULL,
+						 (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+						 &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
+			return IMG_FALSE;
+		}
+
+		/*
+			Force the page to read only, we will make it read/write as
+			and when we need to
+		*/
+		MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
+
+		/* translate address to device physical */
+		if(psPTInfoList->PTPageCpuVAddr)
+		{
+			sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
+										  psPTInfoList->PTPageCpuVAddr);
+		}
+		else
+		{
+			/* This isn't used in all cases since not all ports currently support
+			 * OSMemHandleToCpuPAddr() */
+			sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
+		}
+
+		sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+	}
+	else
+	{
+		/* 
+		   We cannot use IMG_SYS_PHYADDR here, as that is 64-bit for 32-bit PAE builds.
+		   The physical address in this call to RA_Alloc is specifically the SysPAddr 
+		   of local (card) space, and it is highly unlikely we would ever need to 
+		   support > 4GB of local (card) memory (this does assume that such local
+		   memory will be mapped into System physical memory space at a low address so
+		   that any and all local memory exists within the 4GB SYSPAddr range).
+		 */
+		IMG_UINTPTR_T uiLocalPAddr;
+		IMG_SYS_PHYADDR sSysPAddr;
+
+		/*
+			just allocate from the first local memory arena
+			(unlikely to be more than one local mem area(?))
+		*/
+		//FIXME: just allocate a 4K page for each PT for now
+		if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
+					SGX_MMU_PAGE_SIZE,//pMMUHeap->ui32PTSize,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,//pMMUHeap->ui32PTSize,
+					0,
+					IMG_NULL,
+					0,
+					&uiLocalPAddr)!= IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to RA_Alloc failed"));
+			return IMG_FALSE;
+		}
+
+		/* Munge the local PAddr back into the SysPAddr */
+		sSysPAddr.uiAddr = uiLocalPAddr;
+
+		/* derive the CPU virtual address */
+		sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+		/* note: actual ammount is pMMUHeap->ui32PTSize but must be a multiple of 4k pages */
+		psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+													SGX_MMU_PAGE_SIZE,
+													PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+													&psPTInfoList->hPTPageOSMemHandle);
+		if(!psPTInfoList->PTPageCpuVAddr)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR failed to map page tables"));
+			return IMG_FALSE;
+		}
+
+		/* translate address to device physical */
+		sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+		#if PAGE_TEST
+		PageTest(psPTInfoList->PTPageCpuVAddr, sDevPAddr);
+		#endif
+	}
+
+	PVR_ASSERT(psPTInfoList->PTPageCpuVAddr != IMG_NULL);
+
+	MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+	{
+		IMG_UINT32 *pui32Tmp;
+		IMG_UINT32 i;
+
+		pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+		/* point the new PT entries to the dummy data page */
+		for(i=0; i<pMMUHeap->ui32PTNumEntriesUsable; i++)
+		{
+			pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+						| SGX_MMU_PTE_VALID;
+		}
+		/* zero the remaining allocated entries, if any */
+		for(; i<pMMUHeap->ui32PTNumEntriesAllocated; i++)
+		{
+			pui32Tmp[i] = 0;
+		}
+	}
+#else
+	/* Zero the page table. */
+	OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
+#endif
+	MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
+
+#if defined(PDUMP)
+	{
+		IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+		/* make sure shared heap PT allocs are always pdumped */
+		ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+		/* pdump the PT malloc */
+		PDUMPMALLOCPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, psPTInfoList->hPTPageOSMemHandle, 0, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+		/* pdump the PT Pages */
+		PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfoList->hPTPageOSMemHandle, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	}
+#endif
+
+	/* return the DevPAddr */
+	*psDevPAddr = sDevPAddr;
+
+	return IMG_TRUE;
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   _FreePageTableMemory
+
+	PURPOSE:    Free physical memory for a page table
+
+	PARAMETERS: In: pMMUHeap - the mmu
+				In: psPTInfoList - PT info to free
+	RETURNS:    NONE
+******************************************************************************/
+static IMG_VOID
+_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
+{
+	/*
+		free the PT page:
+		depending on the specific system, pagetables are allocated from system memory
+		or device local memory.  For now, just look for at least a valid local heap/arena
+	*/
+	if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+	{
+		/* Force the page to read write before we free it*/
+		MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
+
+		//FIXME: replace with an RA, this allocator only handles 4k allocs
+		OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+					  pMMUHeap->ui32PTSize,
+					  psPTInfoList->PTPageCpuVAddr,
+					  psPTInfoList->hPTPageOSMemHandle);
+	}
+	else
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+		IMG_CPU_PHYADDR sCpuPAddr;
+
+		/*  derive the system physical address */
+		sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle, 
+									  psPTInfoList->PTPageCpuVAddr);
+		sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
+
+		/* unmap the CPU mapping */
+		/* note: actual ammount is pMMUHeap->ui32PTSize but must be a multiple of 4k pages */
+		OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
+                         SGX_MMU_PAGE_SIZE,
+                         PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                         psPTInfoList->hPTPageOSMemHandle);
+
+		/*
+			just free from the first local memory arena
+			(unlikely to be more than one local mem area(?))
+			Note that the cast to IMG_UINTPTR_T is ok as we're local mem.
+		*/
+		RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, (IMG_UINTPTR_T)sSysPAddr.uiAddr, IMG_FALSE);
+	}
+}
+
+
+
+/*!
+******************************************************************************
+	FUNCTION:   _DeferredFreePageTable
+
+	PURPOSE:    Free one page table associated with an MMU.
+
+	PARAMETERS: In:  pMMUHeap - the mmu heap
+				In:  ui32PTIndex - index of the page table to free relative
+								   to the base of heap.
+	RETURNS:    None
+******************************************************************************/
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
+{
+	IMG_UINT32 *pui32PDEntry;
+	IMG_UINT32 i;
+	IMG_UINT32 ui32PDIndex;
+	SYS_DATA *psSysData;
+	MMU_PT_INFO **ppsPTInfoList;
+
+	SysAcquireData(&psSysData);
+
+	/* find the index/offset in PD entries  */
+	ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+	/* set the base PT info */
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+	{
+#if PT_DEBUG
+		if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
+		{
+			DumpPT(ppsPTInfoList[ui32PTIndex]);
+			/* Fall-through, will fail assert */
+		}
+#endif
+
+		/* Assert that all mappings have gone */
+		PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
+	}
+
+#if defined(PDUMP)
+	{
+		IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+		ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+		/* pdump the PT free */
+		PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+		if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
+		{
+			PDUMPFREEPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, ppsPTInfoList[ui32PTIndex]->hPTPageOSMemHandle, ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+		}
+	}
+#endif
+
+	switch(pMMUHeap->psDevArena->DevMemHeapType)
+	{
+		case DEVICE_MEMORY_HEAP_SHARED :
+		case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+		{
+			/* Remove Page Table from all memory contexts */
+			MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+			while(psMMUContext)
+			{
+				/* get the PD CPUVAddr base and advance to the first entry */
+				MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+				pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+				pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+				/* point the PD entry to the dummy PT */
+				pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+											>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+											| SGX_MMU_PDE_PAGE_SIZE_4K
+											| SGX_MMU_PDE_VALID;
+#else
+				/* free the entry */
+				if(bOSFreePT)
+				{
+					pui32PDEntry[ui32PTIndex] = 0;
+				}
+#endif
+				MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+			#if defined(PDUMP)
+				/* pdump the PD Page modifications */
+			#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+				if(psMMUContext->bPDumpActive)
+			#endif
+				{
+					PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+				}
+			#endif
+				/* advance to next context */
+				psMMUContext = psMMUContext->psNext;
+			}
+			break;
+		}
+		case DEVICE_MEMORY_HEAP_PERCONTEXT :
+		case DEVICE_MEMORY_HEAP_KERNEL :
+		{
+			MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+			/* Remove Page Table from this memory context only */
+			pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+			pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+			/* point the PD entry to the dummy PT */
+			pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+										>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+										| SGX_MMU_PDE_PAGE_SIZE_4K
+										| SGX_MMU_PDE_VALID;
+#else
+			/* free the entry */
+			if(bOSFreePT)
+			{
+				pui32PDEntry[ui32PTIndex] = 0;
+			}
+#endif
+			MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+
+			/* pdump the PD Page modifications */
+			PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+			break;
+		}
+		default:
+		{
+			PVR_DPF((PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type"));
+			return;
+		}
+	}
+
+	/* clear the PT entries in each PT page */
+	if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
+	{
+		if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
+		{
+			IMG_PUINT32 pui32Tmp;
+
+			MakeKernelPageReadWrite(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
+			pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
+
+			/* clear the entries */
+			for(i=0;
+				(i<pMMUHeap->ui32PTETotalUsable) && (i<pMMUHeap->ui32PTNumEntriesUsable);
+				 i++)
+			{
+				/* over-allocated PT entries for 4MB data page case should never be non-zero */
+				pui32Tmp[i] = 0;
+			}
+			MakeKernelPageReadOnly(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
+
+			/*
+				free the pagetable memory
+			*/
+			if(bOSFreePT)
+			{
+				_FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
+			}
+
+			/*
+				decrement the PT Entry Count by the number
+				of entries we've cleared in this pass
+			*/
+			pMMUHeap->ui32PTETotalUsable -= i;
+		}
+		else
+		{
+			/* decrement the PT Entry Count by a page's worth of entries  */
+			pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
+		}
+
+		if(bOSFreePT)
+		{
+			/* free the pt info */
+			OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(MMU_PT_INFO),
+						ppsPTInfoList[ui32PTIndex],
+						IMG_NULL);
+			ppsPTInfoList[ui32PTIndex] = IMG_NULL;
+		}
+	}
+	else
+	{
+		/* decrement the PT Entry Count by a page's worth of usable entries */
+		pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
+	}
+
+	PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   _DeferredFreePageTables
+
+	PURPOSE:    Free the page tables associated with an MMU.
+
+	PARAMETERS: In:  pMMUHeap - the mmu
+	RETURNS:    None
+******************************************************************************/
+static IMG_VOID
+_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
+{
+	IMG_UINT32 i;
+#if defined(FIX_HW_BRN_31620)
+	MMU_CONTEXT *psMMUContext = pMMUHeap->psMMUContext;
+	IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 *pui32Tmp;
+	IMG_UINT32 j;
+#endif
+#if defined(PDUMP)
+	PDUMPCOMMENT("Free PTs (MMU Context ID == %u, PDBaseIndex == %u, PT count == 0x%x)",
+			pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+			pMMUHeap->ui32PDBaseIndex,
+			pMMUHeap->ui32PageTableCount);
+#endif
+#if defined(FIX_HW_BRN_31620)
+	for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+	{
+		ui32PDIndex = (pMMUHeap->ui32PDBaseIndex + i);
+
+		if (psMMUContext->apsPTInfoList[ui32PDIndex])
+		{
+			if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+			{
+				/*
+				 * We have to do this to setup the dummy page as
+				 * not all heaps are PD cache size or aligned
+				 */
+				for (j=0;j<SGX_MMU_PT_SIZE;j++)
+				{
+					pui32Tmp = (IMG_UINT32 *) psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+					BRN31620InvalidatePageTableEntry(psMMUContext, ui32PDIndex, j, &pui32Tmp[j]);
+				}
+			}
+			/* Free the PT and NULL's out the PTInfo */
+			if (BRN31620FreePageTable(pMMUHeap, ui32PDIndex) == IMG_TRUE)
+			{
+				bInvalidateDirectoryCache = IMG_TRUE;
+			}
+		}
+	}
+
+	/*
+	 * Due to freeing PT's in chunks we might need to flush the PT cache
+	 * rather then the directory cache
+	 */
+	if (bInvalidateDirectoryCache)
+	{
+		MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+	}
+	else
+	{
+		MMU_InvalidatePageTableCache(pMMUHeap->psMMUContext->psDevInfo);
+	}
+#else
+	for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+	{
+		_DeferredFreePageTable(pMMUHeap, i, IMG_TRUE);
+	}
+	MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   _DeferredAllocPagetables
+
+	PURPOSE:    allocates page tables at time of allocation
+
+	PARAMETERS: In:  pMMUHeap - the mmu heap
+					 DevVAddr - devVAddr of allocation
+					 ui32Size - size of allocation
+	RETURNS:    IMG_TRUE - Success
+	            IMG_FALSE - Failed
+******************************************************************************/
+static IMG_BOOL
+_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+	IMG_UINT32 ui32PageTableCount;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 i;
+	IMG_UINT32 *pui32PDEntry;
+	MMU_PT_INFO **ppsPTInfoList;
+	SYS_DATA *psSysData;
+	IMG_DEV_VIRTADDR sHighDevVAddr;
+#if defined(FIX_HW_BRN_31620)
+	IMG_BOOL bFlushSystemCache = IMG_FALSE;
+	IMG_BOOL bSharedPT = IMG_FALSE;
+	IMG_DEV_VIRTADDR sDevVAddrRequestStart;
+	IMG_DEV_VIRTADDR sDevVAddrRequestEnd;
+	IMG_UINT32 ui32PDRequestStart;
+	IMG_UINT32 ui32PDRequestEnd;
+	IMG_UINT32 ui32ModifiedCachelines[BRN31620_CACHE_FLUSH_INDEX_SIZE];
+#endif
+
+	/* Check device linear address */
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
+	PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
+#endif
+
+	/* get the sysdata */
+	SysAcquireData(&psSysData);
+
+	/* find the index/offset in PD entries  */
+	ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+	/* how many PDs does the allocation occupy? */
+	/* first check for overflows */
+	if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
+		< (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
+	{
+		/* detected overflow, clamp to highest address, reserve all PDs */
+		sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+		ui32PageTableCount = 1024;
+	}
+	else
+	{
+		sHighDevVAddr.uiAddr = DevVAddr.uiAddr
+								+ ui32Size
+								+ pMMUHeap->ui32DataPageMask
+								+ pMMUHeap->ui32PTMask;
+
+		ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+	}
+
+
+	/* Fix allocation of last 4MB */
+	if (ui32PageTableCount == 0)
+		ui32PageTableCount = 1024;
+
+#if defined(FIX_HW_BRN_31620)
+	for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+	{
+		ui32ModifiedCachelines[i] = 0;
+	}
+
+	/*****************************************************************/
+	/* Save off requested data and round allocation to PD cache line */
+	/*****************************************************************/
+	sDevVAddrRequestStart = DevVAddr;
+	ui32PDRequestStart = ui32PDIndex;
+	sDevVAddrRequestEnd = sHighDevVAddr;
+	ui32PDRequestEnd = ui32PageTableCount - 1;
+
+	/* Round allocations down to the PD cacheline */
+	DevVAddr.uiAddr = DevVAddr.uiAddr & (~BRN31620_PDE_CACHE_FILL_MASK);
+
+	/* Round the end address of the PD allocation to cacheline */
+	if (UINT32_MAX_VALUE - sHighDevVAddr.uiAddr < (BRN31620_PDE_CACHE_FILL_SIZE - 1))
+	{
+		sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+		ui32PageTableCount = 1024;
+	}
+	else
+	{
+		sHighDevVAddr.uiAddr = ((sHighDevVAddr.uiAddr + (BRN31620_PDE_CACHE_FILL_SIZE - 1)) & (~BRN31620_PDE_CACHE_FILL_MASK));
+		ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+	}
+
+	ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+	/* Fix allocation of last 4MB */
+	if (ui32PageTableCount == 0)
+		ui32PageTableCount = 1024;
+#endif
+
+	ui32PageTableCount -= ui32PDIndex;
+
+	/* get the PD CPUVAddr base and advance to the first entry */
+	pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+	pui32PDEntry += ui32PDIndex;
+
+	/* and advance to the first PT info list */
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+#if defined(PDUMP)
+	{
+		IMG_UINT32 ui32Flags = 0;
+		
+		/* pdump the PD Page modifications */
+		if( MMU_IsHeapShared(pMMUHeap) )
+		{
+			ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+		}
+		PDUMPCOMMENTWITHFLAGS(ui32Flags, "Alloc PTs (MMU Context ID == %u, PDBaseIndex == %u, Size == 0x%x, Shared = %s)",
+				pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+				pMMUHeap->ui32PDBaseIndex,
+				ui32Size,
+				MMU_IsHeapShared(pMMUHeap)?"True":"False");
+		PDUMPCOMMENTWITHFLAGS(ui32Flags, "Alloc page table (page count == %08X)", ui32PageTableCount);
+		PDUMPCOMMENTWITHFLAGS(ui32Flags, "Page directory mods (page count == %08X)", ui32PageTableCount);
+	}
+#endif
+	/* walk the psPTInfoList to see what needs allocating: */
+	for(i=0; i<ui32PageTableCount; i++)
+	{
+		if(ppsPTInfoList[i] == IMG_NULL)
+		{
+#if defined(FIX_HW_BRN_31620)
+			/* Check if we have a saved PT (i.e. this PDE cache line is still live) */
+			if (pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i])
+			{
+				/* Only make this PTInfo "live" if it's requested */
+				if (((ui32PDIndex + i) >= ui32PDRequestStart) && ((ui32PDIndex + i) <= ui32PDRequestEnd))
+				{
+					IMG_UINT32 ui32PDCacheLine = (ui32PDIndex + i) >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
+
+					ppsPTInfoList[i] = pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i];
+					pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i] = IMG_NULL;
+
+					pMMUHeap->psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine]++;
+				}
+			}
+			else
+			{
+#endif
+			OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						 sizeof (MMU_PT_INFO),
+						 (IMG_VOID **)&ppsPTInfoList[i], IMG_NULL,
+						 "MMU Page Table Info");
+			if (ppsPTInfoList[i] == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to OSAllocMem failed"));
+				return IMG_FALSE;
+			}
+			OSMemSet (ppsPTInfoList[i], 0, sizeof(MMU_PT_INFO));
+#if defined(FIX_HW_BRN_31620)
+			}
+#endif
+		}
+#if defined(FIX_HW_BRN_31620)
+		/* Only try to allocate if ppsPTInfoList[i] is valid */
+		if (ppsPTInfoList[i])
+		{
+#endif
+		if(ppsPTInfoList[i]->hPTPageOSMemHandle == IMG_NULL
+		&& ppsPTInfoList[i]->PTPageCpuVAddr == IMG_NULL)
+		{
+			IMG_DEV_PHYADDR	sDevPAddr = { 0 };
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+			IMG_UINT32 *pui32Tmp;
+			IMG_UINT32 j;
+#else
+#if !defined(FIX_HW_BRN_31620)
+			/* no page table has been allocated so allocate one */
+			PVR_ASSERT(pui32PDEntry[i] == 0);
+#endif
+#endif
+			if(_AllocPageTableMemory (pMMUHeap, ppsPTInfoList[i], &sDevPAddr) != IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to _AllocPageTableMemory failed"));
+				return IMG_FALSE;
+			}
+#if defined(FIX_HW_BRN_31620)
+			bFlushSystemCache = IMG_TRUE;
+			/* Bump up the page table count if required */
+			{
+				IMG_UINT32 ui32PD;
+				IMG_UINT32 ui32PDCacheLine;
+				IMG_UINT32 ui32PDBitMaskIndex;
+				IMG_UINT32 ui32PDBitMaskShift;
+
+				ui32PD = ui32PDIndex + i;
+				ui32PDCacheLine = ui32PD >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
+				ui32PDBitMaskIndex = ui32PDCacheLine >> BRN31620_CACHE_FLUSH_BITS_SHIFT;
+				ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
+				ui32ModifiedCachelines[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
+
+				/* Add 1 to ui32PD as we want the count, not a range */
+				if ((pMMUHeap->ui32PDBaseIndex + pMMUHeap->ui32PageTableCount) < (ui32PD + 1))
+				{
+					pMMUHeap->ui32PageTableCount = (ui32PD + 1) - pMMUHeap->ui32PDBaseIndex;
+				}
+
+				if (((ui32PDIndex + i) >= ui32PDRequestStart) && ((ui32PDIndex + i) <= ui32PDRequestEnd))
+				{
+					pMMUHeap->psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine]++;
+				}
+			}
+#endif
+			switch(pMMUHeap->psDevArena->DevMemHeapType)
+			{
+				case DEVICE_MEMORY_HEAP_SHARED :
+				case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+				{
+					/* insert Page Table into all memory contexts */
+					MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+					PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
+#endif
+					while(psMMUContext)
+					{
+						MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+						/* get the PD CPUVAddr base and advance to the first entry */
+						pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+						pui32PDEntry += ui32PDIndex;
+
+						/* insert the page, specify the data page size and make the pde valid */
+						pui32PDEntry[i] = (IMG_UINT32)(sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+										| pMMUHeap->ui32PDEPageSizeCtrl
+										| SGX_MMU_PDE_VALID;
+						MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+						#if defined(PDUMP)
+						/* pdump the PD Page modifications */
+						#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+						if(psMMUContext->bPDumpActive)
+						#endif
+						{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+							/*
+								Any modification of the uKernel memory context
+								needs to be PDumped when we're multi-process
+							 */
+							IMG_UINT32 ui32HeapFlags = ( psMMUContext->sPDDevPAddr.uiAddr == psDevInfo->sKernelPDDevPAddr.uiAddr ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#else
+							IMG_UINT32 ui32HeapFlags = 0;
+#endif
+							PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), ui32HeapFlags, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+						}
+						#endif /* PDUMP */
+						/* advance to next context */
+						psMMUContext = psMMUContext->psNext;
+					}
+#if defined(FIX_HW_BRN_31620)
+					bSharedPT = IMG_TRUE;
+#endif
+					break;
+				}
+				case DEVICE_MEMORY_HEAP_PERCONTEXT :
+				case DEVICE_MEMORY_HEAP_KERNEL :
+				{
+					MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+					/* insert Page Table into only this memory context */
+					pui32PDEntry[i] = (IMG_UINT32)(sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+									| pMMUHeap->ui32PDEPageSizeCtrl
+									| SGX_MMU_PDE_VALID;
+					MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+					/* pdump the PD Page modifications */
+					PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+					break;
+				}
+				default:
+				{
+					PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR invalid heap type"));
+					return IMG_FALSE;
+				}
+			}
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+			/* This is actually not to do with multiple mem contexts, but to do with the directory cache.
+			   In the 1 context implementation of the MMU, the directory "cache" is actually a copy of the
+			   page directory memory, and requires updating whenever the page directory changes, even if there
+			   was no previous value in a particular entry
+			 */
+			MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+#if defined(FIX_HW_BRN_31620)
+			/* If this PT is not in the requested range then save it and null out the main PTInfo */
+			if (((ui32PDIndex + i) < ui32PDRequestStart) || ((ui32PDIndex + i) > ui32PDRequestEnd))
+			{
+					pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i] = ppsPTInfoList[i];
+					ppsPTInfoList[i] = IMG_NULL;
+			}
+#endif
+		}
+		else
+		{
+#if !defined(FIX_HW_BRN_31620)
+			/* already have an allocated PT */
+			PVR_ASSERT(pui32PDEntry[i] != 0);
+#endif
+		}
+#if defined(FIX_HW_BRN_31620)
+		}
+#endif
+	}
+
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	#if defined(FIX_HW_BRN_31620)
+	/* This function might not allocate any new PT's so check before flushing */
+	if (bFlushSystemCache)
+	#endif
+	{
+		MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
+	}
+	#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+	#if defined(FIX_HW_BRN_31620)
+	/* Handle the last 4MB roll over */
+	sHighDevVAddr.uiAddr = sHighDevVAddr.uiAddr - 1;
+
+	/* Update our PD flush mask if required */
+	if (bFlushSystemCache)
+	{
+		MMU_CONTEXT *psMMUContext;
+
+		if (bSharedPT)
+		{
+			MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+			while(psMMUContext)
+			{
+				for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+				{
+					psMMUContext->ui32PDChangeMask[i] |= ui32ModifiedCachelines[i];
+				}
+
+				/* advance to next context */
+				psMMUContext = psMMUContext->psNext;
+			}
+		}
+		else
+		{
+			for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+			{
+				pMMUHeap->psMMUContext->ui32PDChangeMask[i] |= ui32ModifiedCachelines[i];
+			}
+		}
+
+		/*
+		 * Always hook up the dummy page when we allocate a new range of PTs.
+		 * It might be this is overwritten before the SGX access the dummy page
+		 * but we don't care, it's a lot simpler to add this logic here.
+		 */
+		psMMUContext = pMMUHeap->psMMUContext;
+		for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+		{
+			IMG_UINT32 j;
+
+			for(j=0;j<BRN31620_CACHE_FLUSH_BITS_SIZE;j++)
+			{
+				if (ui32ModifiedCachelines[i] & (1 << j))
+				{
+					PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
+					MMU_PT_INFO *psTempPTInfo = IMG_NULL;
+					IMG_UINT32 *pui32Tmp;
+
+					ui32PDIndex = (((i * BRN31620_CACHE_FLUSH_BITS_SIZE) + j) * BRN31620_PDES_PER_CACHE_LINE_SIZE) + BRN31620_DUMMY_PDE_INDEX;
+
+					/* The PT for the dummy page might not be "live". If not get it from the saved pointer */
+					if (psMMUContext->apsPTInfoList[ui32PDIndex])
+					{
+						psTempPTInfo = psMMUContext->apsPTInfoList[ui32PDIndex];
+					}
+					else
+					{
+						psTempPTInfo = psMMUContext->apsPTInfoListSave[ui32PDIndex];
+					}
+
+					PVR_ASSERT(psTempPTInfo != IMG_NULL);
+
+					MakeKernelPageReadWrite(psTempPTInfo->PTPageCpuVAddr);
+					pui32Tmp = (IMG_UINT32 *) psTempPTInfo->PTPageCpuVAddr;
+					PVR_ASSERT(pui32Tmp != IMG_NULL);
+					pui32Tmp[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+															| SGX_MMU_PTE_DUMMY_PAGE
+															| SGX_MMU_PTE_READONLY
+															| SGX_MMU_PTE_VALID;
+					MakeKernelPageReadOnly(psTempPTInfo->PTPageCpuVAddr);
+					PDUMPCOMMENT("BRN31620 Dump PTE for dummy page after wireing up new PT");
+					PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psTempPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32Tmp[BRN31620_DUMMY_PTE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+				}
+			}
+		}
+	}
+	#endif
+
+	return IMG_TRUE;
+}
+
+
+#if defined(PDUMP)
+/*!
+ *	FUNCTION:	MMU_GetPDumpContextID
+ *
+ *	RETURNS:	pdump MMU context ID
+ */
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext)
+{
+	BM_CONTEXT *pBMContext = hDevMemContext;
+	PVR_ASSERT(pBMContext);
+	/* PRQA S 0505 1 */ /* PVR_ASSERT should catch NULL ptr */
+	return pBMContext->psMMUContext->ui32PDumpMMUContextID;
+}
+
+/*!
+ *	FUNCTION:	MMU_SetPDumpAttribs
+ *
+ *	PURPOSE:	Called from MMU_Initialise and MMU_Create.
+ *				Sets up device-specific attributes for pdumping.
+ *				FIXME: breaks variable size PTs. Really need separate per context
+ *				and per heap attribs.
+ *
+ *	INPUT:		psDeviceNode - used to access deviceID
+ *	INPUT:		ui32DataPageMask - data page mask
+ *	INPUT:		ui32PTSize - PT size
+ *
+ *	OUTPUT:		psMMUAttrib - pdump MMU attributes
+ *
+ *	RETURNS:	none
+ */
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+# error "FIXME: breaks variable size pagetables"
+#endif
+static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib,
+	PVRSRV_DEVICE_NODE *psDeviceNode,
+	IMG_UINT32 ui32DataPageMask,
+	IMG_UINT32 ui32PTSize)
+{
+	/* Sets up device ID, contains pdump memspace name */
+	psMMUAttrib->sDevId = psDeviceNode->sDevId;
+	
+	psMMUAttrib->pszPDRegRegion = IMG_NULL;
+	psMMUAttrib->ui32DataPageMask = ui32DataPageMask;
+	
+	psMMUAttrib->ui32PTEValid = SGX_MMU_PTE_VALID;
+	psMMUAttrib->ui32PTSize = ui32PTSize;
+	psMMUAttrib->ui32PTEAlignShift = SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+	
+	psMMUAttrib->ui32PDEMask = SGX_MMU_PDE_ADDR_MASK;
+	psMMUAttrib->ui32PDEAlignShift = SGX_MMU_PDE_ADDR_ALIGNSHIFT;
+}
+#endif /* PDUMP */
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Initialise
+
+	PURPOSE:	Called from BM_CreateContext.
+				Allocates the top level Page Directory 4k Page for the new context.
+
+	PARAMETERS: None
+	RETURNS:    PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+	IMG_UINT32 *pui32Tmp;
+	IMG_UINT32 i;
+	IMG_CPU_VIRTADDR pvPDCpuVAddr = IMG_NULL;
+	IMG_DEV_PHYADDR sPDDevPAddr = {0};
+	IMG_CPU_PHYADDR sCpuPAddr;
+	MMU_CONTEXT *psMMUContext;
+	IMG_HANDLE hPDOSMemHandle = IMG_NULL;
+	SYS_DATA *psSysData;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+#if defined(PDUMP)
+	PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+	PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise"));
+
+	SysAcquireData(&psSysData);
+#if defined(PDUMP)
+	/* Note: these attribs are on the stack, used only to pdump the MMU context
+	 * creation. */
+	MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+						SGX_MMU_PAGE_MASK,
+						SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+	OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				 sizeof (MMU_CONTEXT),
+				 (IMG_VOID **)&psMMUContext, IMG_NULL,
+				 "MMU Context");
+	if (psMMUContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
+
+	/* stick the devinfo in the context for subsequent use */
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	psMMUContext->psDevInfo = psDevInfo;
+
+	/* record device node for subsequent use */
+	psMMUContext->psDeviceNode = psDeviceNode;
+
+	/* allocate 4k page directory page for the new context */
+	if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
+	{
+		if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						 SGX_MMU_PAGE_SIZE,
+						 SGX_MMU_PAGE_SIZE,
+						 IMG_NULL,
+						 0,
+						 IMG_NULL,
+						 &pvPDCpuVAddr,
+						 &hPDOSMemHandle) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+			eError = PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+			goto exit_setting_values;
+		}
+
+		if(pvPDCpuVAddr)
+		{
+			sCpuPAddr = OSMapLinToCPUPhys(hPDOSMemHandle,
+										  pvPDCpuVAddr);
+		}
+		else
+		{
+			/* This is not used in all cases, since not all ports currently
+			 * support OSMemHandleToCpuPAddr */
+			sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
+		}
+		sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+		#if PAGE_TEST
+		PageTest(pvPDCpuVAddr, sPDDevPAddr);
+		#endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+		/* Allocate dummy PT and Data pages for the first context to be created */
+		if(!psDevInfo->pvMMUContextList)
+		{
+			/* Dummy PT page */
+			if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							 SGX_MMU_PAGE_SIZE,
+							 SGX_MMU_PAGE_SIZE,
+							 IMG_NULL,
+							 0,
+							 IMG_NULL,
+							 &psDevInfo->pvDummyPTPageCpuVAddr,
+							 &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+				goto exit_setting_values;
+			}
+
+			if(psDevInfo->pvDummyPTPageCpuVAddr)
+			{
+				sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+											  psDevInfo->pvDummyPTPageCpuVAddr);
+			}
+			else
+			{
+				/* This is not used in all cases, since not all ports currently
+				 * support OSMemHandleToCpuPAddr */
+				sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
+			}
+			psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+			/* Dummy Data page */
+			if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							 SGX_MMU_PAGE_SIZE,
+							 SGX_MMU_PAGE_SIZE,
+							 IMG_NULL,
+							 0,
+							 IMG_NULL,
+							 &psDevInfo->pvDummyDataPageCpuVAddr,
+							 &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+				goto exit_setting_values;
+			}
+
+			if(psDevInfo->pvDummyDataPageCpuVAddr)
+			{
+				sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+											  psDevInfo->pvDummyDataPageCpuVAddr);
+			}
+			else
+			{
+				sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyDataPageOSMemHandle, 0);
+			}
+			psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+		}
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
+#if defined(FIX_HW_BRN_31620)
+		/* Allocate dummy Data pages for the first context to be created */
+		if(!psDevInfo->pvMMUContextList)
+		{
+			IMG_UINT32 j;
+			/* Allocate dummy page */
+			if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							 SGX_MMU_PAGE_SIZE,
+							 SGX_MMU_PAGE_SIZE,
+							 IMG_NULL,
+							 0,
+							 IMG_NULL,
+							 &psDevInfo->pvBRN31620DummyPageCpuVAddr,
+							 &psDevInfo->hBRN31620DummyPageOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+				goto exit_setting_values;
+			}				
+
+			/* Get a physical address */
+			if(psDevInfo->pvBRN31620DummyPageCpuVAddr)
+			{
+				sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
+											  psDevInfo->pvBRN31620DummyPageCpuVAddr);
+			}
+			else
+			{
+				sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hBRN31620DummyPageOSMemHandle, 0);
+			}
+
+			pui32Tmp = (IMG_UINT32 *)psDevInfo->pvBRN31620DummyPageCpuVAddr;
+			for(j=0; j<(SGX_MMU_PAGE_SIZE/4); j++)
+			{
+				pui32Tmp[j] = BRN31620_DUMMY_PAGE_SIGNATURE;
+			}
+
+			psDevInfo->sBRN31620DummyPageDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+			PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+			/* Allocate dummy PT */
+			if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							 SGX_MMU_PAGE_SIZE,
+							 SGX_MMU_PAGE_SIZE,
+							 IMG_NULL,
+							 0,
+							 IMG_NULL,
+							 &psDevInfo->pvBRN31620DummyPTCpuVAddr,
+							 &psDevInfo->hBRN31620DummyPTOSMemHandle) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+				goto exit_setting_values;
+			}				
+
+			/* Get a physical address */
+			if(psDevInfo->pvBRN31620DummyPTCpuVAddr)
+			{
+				sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
+											  psDevInfo->pvBRN31620DummyPTCpuVAddr);
+			}
+			else
+			{
+				sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hBRN31620DummyPTOSMemHandle, 0);
+			}
+
+			OSMemSet(psDevInfo->pvBRN31620DummyPTCpuVAddr,0,SGX_MMU_PAGE_SIZE);
+			psDevInfo->sBRN31620DummyPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+			PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, 0, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+		}
+#endif
+	}
+	else
+	{
+		/* 
+		   We cannot use IMG_SYS_PHYADDR here, as that is 64-bit for 32-bit PAE builds.
+		   The physical address in this call to RA_Alloc is specifically the SysPAddr 
+		   of local (card) space, and it is highly unlikely we would ever need to 
+		   support > 4GB of local (card) memory (this does assume that such local
+		   memory will be mapped into System physical memory space at a low address so
+		   that any and all local memory exists within the 4GB SYSPAddr range).
+		 */
+		IMG_UINTPTR_T uiLocalPAddr;
+		IMG_SYS_PHYADDR sSysPAddr;
+
+		/* allocate from the device's local memory arena */
+		if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+					SGX_MMU_PAGE_SIZE,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,
+					0,
+					IMG_NULL,
+					0,
+					&uiLocalPAddr)!= IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+			eError = PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+			goto exit_setting_values;
+		}
+
+		/* Munge the local PAddr back into the SysPAddr */
+		sSysPAddr.uiAddr = uiLocalPAddr;
+
+		/* derive the CPU virtual address */
+		sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+		sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+		pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+										SGX_MMU_PAGE_SIZE,
+										PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+										&hPDOSMemHandle);
+		if(!pvPDCpuVAddr)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+			eError = PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+			goto exit_setting_values;
+		}
+
+		#if PAGE_TEST
+		PageTest(pvPDCpuVAddr, sPDDevPAddr);
+		#endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+		/* Allocate dummy PT and Data pages for the first context to be created */
+		if(!psDevInfo->pvMMUContextList)
+		{
+			/* Dummy PT page */
+			if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+						SGX_MMU_PAGE_SIZE,
+						IMG_NULL,
+						IMG_NULL,
+						0,
+						SGX_MMU_PAGE_SIZE,
+						0,
+						IMG_NULL,
+						0,
+						&uiLocalPAddr)!= IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+				goto exit_setting_values;
+			}
+
+			/* Munge the local PAddr back into the SysPAddr */
+			sSysPAddr.uiAddr = uiLocalPAddr;
+
+			/* derive the CPU virtual address */
+			sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+			psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+			psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+																SGX_MMU_PAGE_SIZE,
+																PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+																&psDevInfo->hDummyPTPageOSMemHandle);
+			if(!psDevInfo->pvDummyPTPageCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+				eError = PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+				goto exit_setting_values;
+			}
+
+			/* Dummy Data page */
+			if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+						SGX_MMU_PAGE_SIZE,
+						IMG_NULL,
+						IMG_NULL,
+						0,
+						SGX_MMU_PAGE_SIZE,
+						0,
+						IMG_NULL,
+						0,
+						&uiLocalPAddr)!= IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+				goto exit_setting_values;
+			}
+
+			/* Munge the local PAddr back into the SysPAddr */
+			sSysPAddr.uiAddr = uiLocalPAddr;
+
+			/* derive the CPU virtual address */
+			sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+			psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+			psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+																SGX_MMU_PAGE_SIZE,
+																PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+																&psDevInfo->hDummyDataPageOSMemHandle);
+			if(!psDevInfo->pvDummyDataPageCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+				eError = PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+				goto exit_setting_values;
+			}
+		}
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
+#if defined(FIX_HW_BRN_31620)
+		/* Allocate dummy PT and Data pages for the first context to be created */
+		if(!psDevInfo->pvMMUContextList)
+		{
+			IMG_UINT32 j;
+			/* Allocate dummy page */
+			if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+						SGX_MMU_PAGE_SIZE,
+						IMG_NULL,
+						IMG_NULL,
+						0,
+						SGX_MMU_PAGE_SIZE,
+						0,
+						IMG_NULL,
+						0,
+						&uiLocalPAddr)!= IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+				goto exit_setting_values;
+			}
+
+			/* Munge the local PAddr back into the SysPAddr */
+			sSysPAddr.uiAddr = uiLocalPAddr;
+
+			/* derive the CPU virtual address */
+			sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+			psDevInfo->sBRN31620DummyPageDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+			psDevInfo->pvBRN31620DummyPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+																SGX_MMU_PAGE_SIZE,
+																PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+																&psDevInfo->hBRN31620DummyPageOSMemHandle);
+			if(!psDevInfo->pvBRN31620DummyPageCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+				eError = PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+				goto exit_setting_values;
+			}
+
+			MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPageCpuVAddr);
+			pui32Tmp = (IMG_UINT32 *)psDevInfo->pvBRN31620DummyPageCpuVAddr;
+			for(j=0; j<(SGX_MMU_PAGE_SIZE/4); j++)
+			{
+				pui32Tmp[j] = BRN31620_DUMMY_PAGE_SIGNATURE;
+			}
+			MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPageCpuVAddr);
+			PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+			/* Allocate dummy PT */
+			if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+						SGX_MMU_PAGE_SIZE,
+						IMG_NULL,
+						IMG_NULL,
+						0,
+						SGX_MMU_PAGE_SIZE,
+						0,
+						IMG_NULL,
+						0,
+						&uiLocalPAddr)!= IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+				eError = PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+				goto exit_setting_values;
+			}
+
+			/* Munge the local PAddr back into the SysPAddr */
+			sSysPAddr.uiAddr = uiLocalPAddr;
+
+			/* derive the CPU virtual address */
+			sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+			psDevInfo->sBRN31620DummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+			psDevInfo->pvBRN31620DummyPTCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+																SGX_MMU_PAGE_SIZE,
+																PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+																&psDevInfo->hBRN31620DummyPTOSMemHandle);
+
+			if(!psDevInfo->pvBRN31620DummyPTCpuVAddr)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+				eError = PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+				goto exit_setting_values;
+			}
+
+			OSMemSet(psDevInfo->pvBRN31620DummyPTCpuVAddr,0,SGX_MMU_PAGE_SIZE);		
+			PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, 0, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+		}
+#endif /* #if defined(FIX_HW_BRN_31620) */
+	}
+
+#if defined(FIX_HW_BRN_31620)
+	if (!psDevInfo->pvMMUContextList)
+	{
+		/* Save the kernel MMU context which is always the 1st to be created */
+		psDevInfo->hKernelMMUContext = psMMUContext;
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: saving kernel mmu context: %p", psMMUContext));
+	}
+#endif
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	/* Find out if this context is for the active pdump client.
+	 * If it is, need to ensure PD entries are pdumped whenever another
+	 * process allocates from a shared heap. */
+	{
+		PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+		if(psPerProc == IMG_NULL)
+		{
+			/* changes to the kernel context PD/PTs should be pdumped */
+			psMMUContext->bPDumpActive = IMG_TRUE;
+		}
+		else
+		{
+			psMMUContext->bPDumpActive = psPerProc->bPDumpActive;
+		}
+	}
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+	/* pdump the PD malloc */
+	PDUMPCOMMENT("Alloc page directory for new MMU context (PDDevPAddr == 0x" DEVPADDR_FMT ")", sPDDevPAddr.uiAddr);
+	PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDOSMemHandle, 0, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+#endif /* PDUMP */
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(psMMUContext);
+#endif
+
+	if (pvPDCpuVAddr)
+	{
+		pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"));
+		eError = PVRSRV_ERROR_INVALID_CPU_ADDR;
+		goto exit_setting_values;
+	}
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+	MakeKernelPageReadWrite(pvPDCpuVAddr);
+	/*  wire-up the new PD to the dummy PT */
+	for(i=0; i<SGX_MMU_PD_SIZE; i++)
+	{
+		pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+					| SGX_MMU_PDE_PAGE_SIZE_4K
+					| SGX_MMU_PDE_VALID;
+	}
+	MakeKernelPageReadOnly(pvPDCpuVAddr);
+
+	if(!psDevInfo->pvMMUContextList)
+	{
+		/*
+			if we've just allocated the dummy pages
+			wire up the dummy PT to the dummy data page
+		*/
+		MakeKernelPageReadWrite(psDevInfo->pvDummyPTPageCpuVAddr);
+		pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
+		for(i=0; i<SGX_MMU_PT_SIZE; i++)
+		{
+			pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+						| SGX_MMU_PTE_VALID;
+		}
+		MakeKernelPageReadOnly(psDevInfo->pvDummyPTPageCpuVAddr);
+		/* pdump the Dummy PT Page */
+		PDUMPCOMMENT("Dummy Page table contents");
+		PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyPTPageOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+		/*
+			write a signature to the dummy data page
+		*/
+		MakeKernelPageReadWrite(psDevInfo->pvDummyDataPageCpuVAddr);
+		pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
+		for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
+		{
+			pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
+		}
+		MakeKernelPageReadOnly(psDevInfo->pvDummyDataPageCpuVAddr);
+		/* pdump the Dummy Data Page */
+		PDUMPCOMMENT("Dummy Data Page contents");
+		PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	}
+#else /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
+	/* initialise the PD to invalid address state */
+	MakeKernelPageReadWrite(pvPDCpuVAddr);
+	for(i=0; i<SGX_MMU_PD_SIZE; i++)
+	{
+		/* invalid, no read, no write, no cache consistency */
+		pui32Tmp[i] = 0;
+	}
+	MakeKernelPageReadOnly(pvPDCpuVAddr);
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	if(psMMUContext->bPDumpActive)
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+	{
+		/* pdump the PD Page */
+		PDUMPCOMMENT("Page directory contents");
+		PDUMPPDENTRIES(&sMMUAttrib, hPDOSMemHandle, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	}
+#endif
+#if defined(FIX_HW_BRN_31620)
+	{
+		IMG_UINT32 i;
+		IMG_UINT32 ui32PDCount = 0;
+		IMG_UINT32 *pui32PT;
+		pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+
+		PDUMPCOMMENT("BRN31620 Set up dummy PT");
+
+		MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPTCpuVAddr);
+		pui32PT = (IMG_UINT32 *) psDevInfo->pvBRN31620DummyPTCpuVAddr;
+		pui32PT[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+								| SGX_MMU_PTE_DUMMY_PAGE
+								| SGX_MMU_PTE_READONLY
+								| SGX_MMU_PTE_VALID;
+		MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPTCpuVAddr);
+
+#if defined(PDUMP)
+		/* Dump initial contents */
+		PDUMPCOMMENT("BRN31620 Dump dummy PT contents");
+		PDUMPMEMPTENTRIES(&sMMUAttrib,  psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+		PDUMPCOMMENT("BRN31620 Dump dummy page contents");
+		PDUMPMEMPTENTRIES(&sMMUAttrib,  psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+		/* Dump the wiring */		
+		for(i=0;i<SGX_MMU_PT_SIZE;i++)
+		{
+			PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPTOSMemHandle, &pui32PT[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+		}
+#endif
+		PDUMPCOMMENT("BRN31620 Dump PDE wire up");
+		/* Walk the PD wireing up the PT's */
+		for(i=0;i<SGX_MMU_PD_SIZE;i++)
+		{
+			pui32Tmp[i] = 0;
+
+			if (ui32PDCount == BRN31620_DUMMY_PDE_INDEX)
+			{
+				MakeKernelPageReadWrite(pvPDCpuVAddr);
+				pui32Tmp[i] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+						| SGX_MMU_PDE_PAGE_SIZE_4K
+						| SGX_MMU_PDE_DUMMY_PAGE
+						| SGX_MMU_PDE_VALID;
+				MakeKernelPageReadOnly(pvPDCpuVAddr);
+			}
+				PDUMPMEMPTENTRIES(&sMMUAttrib, hPDOSMemHandle, (IMG_VOID *) &pui32Tmp[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+			ui32PDCount++;
+			if (ui32PDCount == BRN31620_PDES_PER_CACHE_LINE_SIZE)
+			{
+				/* Reset PT count */
+				ui32PDCount = 0;
+			}
+		}
+
+
+		/* pdump the Dummy PT Page */
+		PDUMPCOMMENT("BRN31620 dummy Page table contents");
+		PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+	}
+#endif
+#if defined(PDUMP)
+	/* pdump set MMU context */
+	{
+		/* default MMU type is 1, 4k page */
+		IMG_UINT32 ui32MMUType = 1;
+
+		#if defined(SGX_FEATURE_36BIT_MMU)
+			ui32MMUType = 3;
+		#else
+			#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+				ui32MMUType = 2;
+			#endif
+		#endif
+
+		eError = PDumpSetMMUContext(PVRSRV_DEVICE_TYPE_SGX,
+									psDeviceNode->sDevId.pszPDumpDevName,
+									&psMMUContext->ui32PDumpMMUContextID,
+									ui32MMUType,
+									PDUMP_PT_UNIQUETAG,
+									hPDOSMemHandle,
+									pvPDCpuVAddr);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to PDumpSetMMUContext failed"));
+			goto exit_setting_values;
+		}
+	}
+
+	/* PDump the context ID */
+	PDUMPCOMMENT("Set MMU context complete (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+	for(i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+	{
+		psMMUContext->ui32PDChangeMask[i] = 0;
+	}
+
+	for(i=0;i<BRN31620_CACHE_FLUSH_SIZE;i++)
+	{
+		psMMUContext->ui32PDCacheRangeRefCount[i] = 0;
+	}
+
+	for(i=0;i<SGX_MAX_PD_ENTRIES;i++)
+	{
+		psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
+	}
+#endif
+
+exit_setting_values:
+
+	/* store PD info in the MMU context */
+	psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
+	psMMUContext->sPDDevPAddr = sPDDevPAddr;
+	psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
+
+	/* Get some process information to aid debug */
+	psMMUContext->ui32PID = OSGetCurrentProcessIDKM();
+	psMMUContext->szName[0] = '\0';
+	OSGetCurrentProcessNameKM(psMMUContext->szName, MMU_CONTEXT_NAME_SIZE);
+
+	/* return context */
+	*ppsMMUContext = psMMUContext;
+
+	/* return the PD DevVAddr */
+	*psPDDevPAddr = sPDDevPAddr;
+
+
+	/* add the new MMU context onto the list of MMU contexts */
+	psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+	psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(psMMUContext);
+#endif
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Finalise
+
+	PURPOSE:    Finalise the mmu module, deallocate all resources.
+
+	PARAMETERS: In: psMMUContext - MMU context to deallocate
+	RETURNS:    None.
+******************************************************************************/
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext)
+{
+	IMG_UINT32 *pui32Tmp, i;
+	SYS_DATA *psSysData;
+	MMU_CONTEXT **ppsMMUContext;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined(FIX_HW_BRN_31620)
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+	MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+#endif
+
+	SysAcquireData(&psSysData);
+
+#if defined(PDUMP)
+	{
+		IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+		/* pdump the MMU context clear */
+		PDUMPCOMMENT("Clear MMU context (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+		PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->psDeviceNode->sDevId.pszPDumpDevName, psMMUContext->ui32PDumpMMUContextID, 2);
+
+		/* pdump the PD free */
+		PDUMPCOMMENT("Free page directory (PDDevPAddr == 0x" DEVPADDR_FMT ")",
+				psMMUContext->sPDDevPAddr.uiAddr);
+
+		PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psMMUContext->hPDOSMemHandle, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, ui32Flags, PDUMP_PT_UNIQUETAG);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+		PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyPTPageOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, ui32Flags, PDUMP_PT_UNIQUETAG);
+		PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, ui32Flags, PDUMP_PT_UNIQUETAG);
+#endif
+	}
+#endif /* PDUMP */
+
+	pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
+
+	if (pui32Tmp)
+	{
+		MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+		/* initialise the PD to invalid address state */
+		for(i=0; i<SGX_MMU_PD_SIZE; i++)
+		{
+			/* invalid, no read, no write, no cache consistency */
+			pui32Tmp[i] = 0;
+		}
+		MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+	}
+
+	/*
+		free the PD:
+		depending on the specific system, the PD is allocated from system memory
+		or device local memory.  For now, just look for at least a valid local heap/arena
+	*/
+	if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
+	{
+#if defined(FIX_HW_BRN_31620)
+		PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+#endif
+		MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+		OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						SGX_MMU_PAGE_SIZE,
+						psMMUContext->pvPDCpuVAddr,
+						psMMUContext->hPDOSMemHandle);
+
+#if defined(FIX_HW_BRN_31620)
+		/* If this is the _last_ MMU context it must be the uKernel */
+		if (!psMMUContextList->psNext)
+		{
+			PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							SGX_MMU_PAGE_SIZE,
+							psDevInfo->pvBRN31620DummyPageCpuVAddr,
+							psDevInfo->hBRN31620DummyPageOSMemHandle);
+
+			PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							SGX_MMU_PAGE_SIZE,
+							psDevInfo->pvBRN31620DummyPTCpuVAddr,
+							psDevInfo->hBRN31620DummyPTOSMemHandle);
+	
+		}
+#endif
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+		/* if this is the last context free the dummy pages too */
+		if(!psMMUContextList->psNext)
+		{
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							SGX_MMU_PAGE_SIZE,
+							psDevInfo->pvDummyPTPageCpuVAddr,
+							psDevInfo->hDummyPTPageOSMemHandle);
+			OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+							SGX_MMU_PAGE_SIZE,
+							psDevInfo->pvDummyDataPageCpuVAddr,
+							psDevInfo->hDummyDataPageOSMemHandle);
+		}
+#endif
+	}
+	else
+	{
+		IMG_SYS_PHYADDR sSysPAddr;
+		IMG_CPU_PHYADDR sCpuPAddr;
+
+		/*  derive the system physical address */
+		sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->hPDOSMemHandle,
+									  psMMUContext->pvPDCpuVAddr);
+		sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+		/* unmap the CPU mapping */
+		OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
+							SGX_MMU_PAGE_SIZE,
+                            PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+							psMMUContext->hPDOSMemHandle);
+		/* and free the memory, Note that the cast to IMG_UINTPTR_T is ok as we're local mem. */
+		RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, (IMG_UINTPTR_T)sSysPAddr.uiAddr, IMG_FALSE);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+		/* if this is the last context free the dummy pages too */
+		if(!psMMUContextList->psNext)
+		{
+			/* free the Dummy PT Page */
+			sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+										  psDevInfo->pvDummyPTPageCpuVAddr);
+			sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+			/* unmap the CPU mapping */
+			OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
+								SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								psDevInfo->hDummyPTPageOSMemHandle);
+			/* and free the memory */
+			RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+			/* free the Dummy Data Page */
+			sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyDataPageOSMemHandle,
+										  psDevInfo->pvDummyDataPageCpuVAddr);
+			sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+			/* unmap the CPU mapping */
+			OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
+								SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								psDevInfo->hDummyDataPageOSMemHandle);
+			/* and free the memory */
+			RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+		}
+#endif
+#if defined(FIX_HW_BRN_31620)
+		/* if this is the last context free the dummy pages too */
+		if(!psMMUContextList->psNext)
+		{
+			/* free the Page */
+			PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+			sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
+										  psDevInfo->pvBRN31620DummyPageCpuVAddr);
+			sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+			/* unmap the CPU mapping */
+			OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPageCpuVAddr,
+								SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								psDevInfo->hBRN31620DummyPageOSMemHandle);
+			/* and free the memory */
+			RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+			/* free the Dummy PT */
+			PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+			sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
+										  psDevInfo->pvBRN31620DummyPTCpuVAddr);
+			sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+			/* unmap the CPU mapping */
+			OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPTCpuVAddr,
+								SGX_MMU_PAGE_SIZE,
+                                PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+								psDevInfo->hBRN31620DummyPTOSMemHandle);
+			/* and free the memory */
+			RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+		}
+#endif
+	}
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
+
+	/* remove the MMU context from the list of MMU contexts */
+	ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
+	while(*ppsMMUContext)
+	{
+		if(*ppsMMUContext == psMMUContext)
+		{
+			/* remove item from the list */
+			*ppsMMUContext = psMMUContext->psNext;
+			break;
+		}
+
+		/* advance to next next */
+		ppsMMUContext = &((*ppsMMUContext)->psNext);
+	}
+
+	/* free the context itself. */
+	OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_InsertHeap
+
+	PURPOSE:    Copies PDEs from shared/exported heap into current MMU context.
+
+	PARAMETERS:	In:  psMMUContext - the mmu
+	            In:  psMMUHeap - a shared/exported heap
+
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
+{
+	IMG_UINT32 *pui32PDCpuVAddr = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+	IMG_UINT32 *pui32KernelPDCpuVAddr = (IMG_UINT32 *) psMMUHeap->psMMUContext->pvPDCpuVAddr;
+	IMG_UINT32 ui32PDEntry;
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+#endif
+
+	/* advance to the first entry */
+	pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+	pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+	/*
+		update the PD range relating to the heap's
+		device virtual address range
+	*/
+#if defined(PDUMP)
+	PDUMPCOMMENT("Page directory shared heap range copy");
+	PDUMPCOMMENT("  (Source heap MMU Context ID == %u, PT count == 0x%x)",
+			psMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+			psMMUHeap->ui32PageTableCount);
+	PDUMPCOMMENT("  (Destination MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif /* PDUMP */
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(psMMUContext);
+#endif
+
+	for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
+	{
+#if (!defined(SUPPORT_SGX_MMU_DUMMY_PAGE)) && (!defined(FIX_HW_BRN_31620))
+		/* check we have invalidated target PDEs */
+		PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+#endif
+		MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+		/* copy over the PDEs */
+		pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+		MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
+		if (pui32PDCpuVAddr[ui32PDEntry])
+		{
+			/* Ensure the shared heap allocation is mapped into the context/PD
+			 * for the active pdump process/app. The PTs and backing physical
+			 * should also be pdumped (elsewhere).
+			 *		MALLOC (PT)
+			 *		LDB (init PT)
+			 *		MALLOC (data page)
+			 *		WRW (PTE->data page)
+			 *		LDB (init data page) -- could be useful to ensure page is initialised
+			 */
+		#if defined(PDUMP)
+			//PDUMPCOMMENT("MMU_InsertHeap: Mapping shared heap to new context %d (%s)", psMMUContext->ui32PDumpMMUContextID, (psMMUContext->bPDumpActive) ? "active" : "");
+		#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+			if(psMMUContext->bPDumpActive)
+		#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+			{
+				PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+			}
+		#endif
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+			bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+		}
+	}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(psMMUContext);
+#endif
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	if (bInvalidateDirectoryCache)
+	{
+		/* This is actually not to do with multiple mem contexts, but to do with the directory cache.
+			In the 1 context implementation of the MMU, the directory "cache" is actually a copy of the
+			page directory memory, and requires updating whenever the page directory changes, even if there
+			was no previous value in a particular entry
+		*/
+		MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
+	}
+#endif
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_UnmapPagesAndFreePTs
+
+	PURPOSE:    unmap pages, invalidate virtual address and try to free the PTs
+
+	PARAMETERS:	In:  psMMUHeap - the mmu.
+	            In:  sDevVAddr - the device virtual address.
+	            In:  ui32PageCount - page count
+	            In:  hUniqueTag - A unique ID for use as a tag identifier
+
+	RETURNS:	None
+******************************************************************************/
+static IMG_VOID
+MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
+						  IMG_DEV_VIRTADDR sDevVAddr,
+						  IMG_UINT32 ui32PageCount,
+						  IMG_HANDLE hUniqueTag)
+{
+	IMG_DEV_VIRTADDR	sTmpDevVAddr;
+	IMG_UINT32			i;
+	IMG_UINT32			ui32PDIndex;
+	IMG_UINT32			ui32PTIndex;
+	IMG_UINT32			*pui32Tmp;
+	IMG_BOOL			bInvalidateDirectoryCache = IMG_FALSE;
+
+#if !defined (PDUMP)
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+	/* setup tmp devvaddr to base of allocation */
+	sTmpDevVAddr = sDevVAddr;
+
+	for(i=0; i<ui32PageCount; i++)
+	{
+		MMU_PT_INFO **ppsPTInfoList;
+
+		/* find the index/offset in PD entries  */
+		ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+		/* and advance to the first PT info list */
+		ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+		{
+			/* find the index/offset of the first PT in the first PT page */
+			ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+			/* Is the PT page valid? */
+			if (!ppsPTInfoList[0])
+			{
+				/*
+					With sparse mappings we expect that the PT could be freed
+					before we reach the end of it as the unmapped pages don't
+					bump ui32ValidPTECount so it can reach zero before we reach
+					the end of the PT.
+				*/
+				if (!psMMUHeap->bHasSparseMappings)
+				{
+					PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+				}
+
+				/* advance the sTmpDevVAddr by one page */
+				sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+
+				/* Try to unmap the remaining allocation pages */
+				continue;
+			}
+
+			/* setup pointer to the first entry in the PT page */
+			pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+			/* Is PTPageCpuVAddr valid ? */
+			if (!pui32Tmp)
+			{
+				continue;
+			}
+
+			CheckPT(ppsPTInfoList[0]);
+
+			/* Decrement the valid page count only if the current page is valid*/
+			if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+			{
+				ppsPTInfoList[0]->ui32ValidPTECount--;
+			}
+			else
+			{
+				if (!psMMUHeap->bHasSparseMappings)
+				{
+					PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+				}
+			}
+
+			/* The page table count should not go below zero */
+			PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+			MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+			/* point the PT entry to the dummy data page */
+			pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+									| SGX_MMU_PTE_VALID;
+#else
+			/* invalidate entry */
+#if defined(FIX_HW_BRN_31620)
+			BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
+#else
+			pui32Tmp[ui32PTIndex] = 0;
+#endif
+#endif
+			MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
+			CheckPT(ppsPTInfoList[0]);
+		}
+
+		/*
+			Free a page table if we can.
+		*/
+		if (ppsPTInfoList[0] && (ppsPTInfoList[0]->ui32ValidPTECount == 0)
+			)
+		{
+#if defined(FIX_HW_BRN_31620)
+			if (BRN31620FreePageTable(psMMUHeap, ui32PDIndex) == IMG_TRUE)
+			{
+				bInvalidateDirectoryCache = IMG_TRUE;
+			}
+#else
+			_DeferredFreePageTable(psMMUHeap, ui32PDIndex - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+			bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+		}
+
+		/* advance the sTmpDevVAddr by one page */
+		sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+	}
+
+	if(bInvalidateDirectoryCache)
+	{
+		MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->psDevInfo);
+	}
+	else
+	{
+		MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+	}
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables(psMMUHeap,
+						sDevVAddr,
+						psMMUHeap->ui32DataPageSize * ui32PageCount,
+						IMG_TRUE,
+						hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_FreePageTables
+
+	PURPOSE:    Call back from RA_Free to zero page table entries used by freed
+				spans.
+
+	PARAMETERS: In: pvMMUHeap
+				In: ui32Start
+				In: ui32End
+				In: hUniqueTag - A unique ID for use as a tag identifier
+	RETURNS:
+******************************************************************************/
+static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
+                                   IMG_SIZE_T uStart,
+                                   IMG_SIZE_T uEnd,
+                                   IMG_HANDLE hUniqueTag)
+{
+	MMU_HEAP *pMMUHeap = (MMU_HEAP*)pvMMUHeap;
+	IMG_DEV_VIRTADDR Start;
+
+	Start.uiAddr = (IMG_UINT32)uStart;
+
+	MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (IMG_UINT32)((uEnd - uStart) >> pMMUHeap->ui32PTShift), hUniqueTag);
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Create
+
+	PURPOSE:    Create an mmu device virtual heap.
+
+	PARAMETERS: In: psMMUContext - MMU context
+	            In: psDevArena - device memory resource arena
+				Out: ppsVMArena - virtual mapping arena
+	RETURNS:	MMU_HEAP
+	RETURNS:
+******************************************************************************/
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+			DEV_ARENA_DESCRIPTOR *psDevArena,
+			RA_ARENA **ppsVMArena,
+			PDUMP_MMU_ATTRIB **ppsMMUAttrib)
+{
+	MMU_HEAP *pMMUHeap;
+	IMG_UINT32 ui32ScaleSize;
+
+	PVR_UNREFERENCED_PARAMETER(ppsMMUAttrib);
+
+	PVR_ASSERT (psDevArena != IMG_NULL);
+
+	if (psDevArena == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid parameter"));
+		return IMG_NULL;
+	}
+
+	OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+				 sizeof (MMU_HEAP),
+				 (IMG_VOID **)&pMMUHeap, IMG_NULL,
+				 "MMU Heap");
+	if (pMMUHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to OSAllocMem failed"));
+		return IMG_NULL;
+	}
+
+	pMMUHeap->psMMUContext = psMMUContext;
+	pMMUHeap->psDevArena = psDevArena;
+
+	/*
+		generate page table and data page mask and shift values
+		based on the data page size
+	*/
+	switch(pMMUHeap->psDevArena->ui32DataPageSize)
+	{
+		case 0x1000:
+			ui32ScaleSize = 0;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4K;
+			break;
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+		case 0x4000:
+			ui32ScaleSize = 2;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_16K;
+			break;
+		case 0x10000:
+			ui32ScaleSize = 4;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_64K;
+			break;
+		case 0x40000:
+			ui32ScaleSize = 6;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_256K;
+			break;
+		case 0x100000:
+			ui32ScaleSize = 8;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_1M;
+			break;
+		case 0x400000:
+			ui32ScaleSize = 10;
+			pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
+			break;
+#endif /* #if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE) */
+		default:
+			PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
+			goto ErrorFreeHeap;
+	}
+
+	/* number of bits of address offset into the data page */
+	pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
+	pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
+	pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
+	/* number of bits of address indexing into a pagetable */
+	pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
+	pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
+	pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
+	pMMUHeap->ui32PTSize = (IMG_UINT32)(1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
+
+	/* note: PT size must be at least 4 entries, even for 4Mb data page size */
+	if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
+	{
+		pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
+	}
+	pMMUHeap->ui32PTNumEntriesAllocated = pMMUHeap->ui32PTSize >> 2;
+
+	/* find the number of actual PT entries per PD entry range. For 4MB data
+	 * pages we only use the first entry although the PT has 16 byte allocation/alignment
+	 * (due to 4 LSbits of the PDE are reserved for control) */
+	pMMUHeap->ui32PTNumEntriesUsable = (IMG_UINT32)(1UL << pMMUHeap->ui32PTBitWidth);
+
+	/* number of bits of address indexing into a page directory */
+	pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
+	pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
+	pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
+
+	/* External system cache violates this rule */
+#if !defined (SUPPORT_EXTERNAL_SYSTEM_CACHE)
+	/*
+		The heap must start on a PT boundary to avoid PT sharing across heaps
+		The only exception is the first heap which can start at any address
+		from 0 to the end of the first PT boundary
+	*/
+	if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
+	{
+		/*
+			if for some reason the first heap starts after the end of the first PT boundary
+			but is not aligned to a PT boundary then the assert will trigger unncessarily
+		*/
+		PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
+						& (pMMUHeap->ui32DataPageMask
+							| pMMUHeap->ui32PTMask)) == 0);
+	}
+#endif
+	/* how many PT entries do we need? */
+	pMMUHeap->ui32PTETotalUsable = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
+
+	/* calculate the PD Base index for the Heap (required for page mapping) */
+	pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
+
+	/*
+		how many page tables?
+		round up to nearest entries to the nearest page table sized block
+	*/
+	pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotalUsable + pMMUHeap->ui32PTNumEntriesUsable - 1)
+										>> pMMUHeap->ui32PTBitWidth;
+	PVR_ASSERT(pMMUHeap->ui32PageTableCount > 0);
+
+	/* Create the arena */
+	pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+									psDevArena->BaseDevVAddr.uiAddr,
+									psDevArena->ui32Size,
+									IMG_NULL,
+									MIN(HOST_PAGESIZE(), pMMUHeap->ui32DataPageSize),
+									IMG_NULL,
+									IMG_NULL,
+									&MMU_FreePageTables,
+									pMMUHeap);
+
+	if (pMMUHeap->psVMArena == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
+		goto ErrorFreePagetables;
+	}
+
+#if defined(PDUMP)
+	/* setup per-heap PDUMP MMU attributes */
+	MMU_SetPDumpAttribs(&pMMUHeap->sMMUAttrib,
+						psMMUContext->psDeviceNode,
+						pMMUHeap->ui32DataPageMask,
+						pMMUHeap->ui32PTSize);
+	*ppsMMUAttrib = &pMMUHeap->sMMUAttrib;
+
+	PDUMPCOMMENT("Create MMU device from arena %s (Size == 0x%x, DataPageSize == 0x%x, BaseDevVAddr == 0x%x)",
+			psDevArena->pszName,
+			psDevArena->ui32Size,
+			pMMUHeap->ui32DataPageSize,
+			psDevArena->BaseDevVAddr.uiAddr);
+#endif /* PDUMP */
+
+	/*
+		And return the RA for VM arena management
+	*/
+	*ppsVMArena = pMMUHeap->psVMArena;
+
+	return pMMUHeap;
+
+	/* drop into here if errors */
+ErrorFreePagetables:
+	_DeferredFreePageTables (pMMUHeap);
+
+ErrorFreeHeap:
+	OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+	/*not nulling pointer, out of scope*/
+
+	return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Delete
+
+	PURPOSE:    Delete an MMU device virtual heap.
+
+	PARAMETERS: In:  pMMUHeap - The MMU heap to delete.
+	RETURNS:
+******************************************************************************/
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap)
+{
+	if (pMMUHeap != IMG_NULL)
+	{
+		PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete"));
+
+		if(pMMUHeap->psVMArena)
+		{
+			RA_Delete (pMMUHeap->psVMArena);
+		}
+
+#if defined(PDUMP)
+		PDUMPCOMMENT("Delete MMU device from arena %s (BaseDevVAddr == 0x%x, PT count for deferred free == 0x%x)",
+				pMMUHeap->psDevArena->pszName,
+				pMMUHeap->psDevArena->BaseDevVAddr.uiAddr,
+				pMMUHeap->ui32PageTableCount);
+#endif /* PDUMP */
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+		EnableHostAccess(pMMUHeap->psMMUContext);
+#endif
+		_DeferredFreePageTables (pMMUHeap);
+#ifdef SUPPORT_SGX_MMU_BYPASS
+		DisableHostAccess(pMMUHeap->psMMUContext);
+#endif
+
+		OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+	}
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Alloc
+	PURPOSE:    Allocate space in an mmu's virtual address space.
+	PARAMETERS:	In:  pMMUHeap - MMU to allocate on.
+	            In:  uSize - Size in bytes to allocate.
+	            Out: pActualSize - If non null receives actual size allocated.
+	            In:  uFlags - Allocation flags.
+	            In:  uDevVAddrAlignment - Required alignment.
+	            Out: DevVAddr - Receives base address of allocation.
+	RETURNS:	IMG_TRUE - Success
+	            IMG_FALSE - Failure
+******************************************************************************/
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+		   IMG_SIZE_T uSize,
+		   IMG_SIZE_T *pActualSize,
+		   IMG_UINT32 uFlags,
+		   IMG_UINT32 uDevVAddrAlignment,
+		   IMG_DEV_VIRTADDR *psDevVAddr)
+{
+	IMG_BOOL bStatus;
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+		"MMU_Alloc: uSize=0x%" SIZE_T_FMT_LEN "x, flags=0x%x, align=0x%x",
+		uSize, uFlags, uDevVAddrAlignment));
+
+	/*
+		Only allocate a VM address if the caller did not supply one
+	*/
+	if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+	{
+		IMG_UINTPTR_T uiAddr;
+
+		bStatus = RA_Alloc (pMMUHeap->psVMArena,
+							uSize,
+							pActualSize,
+							IMG_NULL,
+							0,
+							uDevVAddrAlignment,
+							0,
+							IMG_NULL,
+							0,
+							&uiAddr);
+		if(!bStatus)
+		{
+			IMG_CHAR asCurrentProcessName[128];
+
+			PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: RA_Alloc of VMArena failed"));	
+			OSGetCurrentProcessNameKM(asCurrentProcessName, 128);
+			PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Alloc of DevVAddr failed from heap %s ID%d, pid: %d, task: %s",
+ 									pMMUHeap->psDevArena->pszName,
+									pMMUHeap->psDevArena->ui32HeapID,
+									OSGetCurrentProcessIDKM(),
+									asCurrentProcessName));									
+		#if defined (MEM_TRACK_INFO_DEBUG)
+			PVRSRVPrintMemTrackInfo(0);
+		#endif
+
+			return bStatus;
+		}
+
+		psDevVAddr->uiAddr = IMG_CAST_TO_DEVVADDR_UINT(uiAddr);
+	}
+
+	#ifdef SUPPORT_SGX_MMU_BYPASS
+	EnableHostAccess(pMMUHeap->psMMUContext);
+	#endif
+
+	/* allocate page tables to cover allocation as required */
+	bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, (IMG_UINT32)uSize);
+
+	#ifdef SUPPORT_SGX_MMU_BYPASS
+	DisableHostAccess(pMMUHeap->psMMUContext);
+	#endif
+
+	if (!bStatus)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed"));
+		PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Failed to alloc pagetable(s) for DevVAddr 0x%8.8x from heap %s ID%d",
+								psDevVAddr->uiAddr,
+								pMMUHeap->psDevArena->pszName,
+								pMMUHeap->psDevArena->ui32HeapID));
+		if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+		{
+			/* free the VM address */
+			RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
+		}
+	}
+
+	return bStatus;
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Free
+	PURPOSE:    Free space in an mmu's virtual address space.
+	PARAMETERS:	In:  pMMUHeap - MMU to deallocate on.
+	            In:  DevVAddr - Base address to deallocate.
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+	PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+	if (pMMUHeap == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter"));
+		return;
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE, "MMU_Free: Freeing DevVAddr 0x%08X from heap %s ID%d",
+								DevVAddr.uiAddr,
+								pMMUHeap->psDevArena->pszName,
+								pMMUHeap->psDevArena->ui32HeapID));
+
+	if((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) &&
+		(DevVAddr.uiAddr + ui32Size <= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr + pMMUHeap->psDevArena->ui32Size))
+	{
+		RA_Free (pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE);
+		return;
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"MMU_Free: Couldn't free DevVAddr %08X from heap %s ID%d (not in range of heap))",
+							DevVAddr.uiAddr,
+							pMMUHeap->psDevArena->pszName,
+							pMMUHeap->psDevArena->ui32HeapID));
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Enable
+
+	PURPOSE:    Enable an mmu. Establishes pages tables and takes the mmu out
+	            of bypass and waits for the mmu to acknowledge enabled.
+
+	PARAMETERS: In:  pMMUHeap - the mmu
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap)
+{
+	PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+	/* SGX mmu is always enabled (stub function) */
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_Disable
+
+	PURPOSE:    Disable an mmu, takes the mmu into bypass.
+
+	PARAMETERS: In:  pMMUHeap - the mmu
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap)
+{
+	PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+	/* SGX mmu is always enabled (stub function) */
+}
+
+#if defined(FIX_HW_BRN_31620)
+/*!
+******************************************************************************
+	FUNCTION:   MMU_GetCacheFlushRange
+
+	PURPOSE:    Gets device physical address of the mmu context.
+
+	PARAMETERS: In:  pMMUContext - the mmu context
+	            Out:  pui32RangeMask - Bit mask showing which PD cache
+		          lines have changed
+	RETURNS:    None
+******************************************************************************/
+
+IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask)
+{
+	IMG_UINT32 i;
+
+	for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
+	{
+		pui32RangeMask[i] = pMMUContext->ui32PDChangeMask[i];
+
+		/* Clear bit mask for the next set of allocations */
+		pMMUContext->ui32PDChangeMask[i] = 0;
+	}
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_GetPDPhysAddr
+
+	PURPOSE:    Gets device physical address of the mmu contexts PD.
+
+	PARAMETERS: In:  pMMUContext - the mmu context
+	            Out:  psDevPAddr - Address of PD
+	RETURNS:    None
+******************************************************************************/
+
+IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr)
+{
+	*psDevPAddr = pMMUContext->sPDDevPAddr;
+}
+
+#endif
+#if defined(PDUMP)
+/*!
+******************************************************************************
+	FUNCTION:   MMU_PDumpPageTables
+
+	PURPOSE:    PDump the linear mapping for a range of pages at a specified
+	            virtual address.
+
+	PARAMETERS: In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  uSize - size of memory range in bytes
+	            In:  hUniqueTag - A unique ID for use as a tag identifier
+	RETURNS:    None
+******************************************************************************/
+static IMG_VOID
+MMU_PDumpPageTables	(MMU_HEAP *pMMUHeap,
+					 IMG_DEV_VIRTADDR DevVAddr,
+					 IMG_SIZE_T uSize,
+					 IMG_BOOL bForUnmap,
+					 IMG_HANDLE hUniqueTag)
+{
+	IMG_UINT32	ui32NumPTEntries;
+	IMG_UINT32	ui32PTIndex;
+	IMG_UINT32	*pui32PTEntry;
+
+	MMU_PT_INFO **ppsPTInfoList;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 ui32PTDumpCount;
+
+#if defined(FIX_HW_BRN_31620)
+	PVRSRV_SGXDEV_INFO *psDevInfo = pMMUHeap->psMMUContext->psDevInfo;
+#endif
+	/* find number of PT entries to dump */
+	ui32NumPTEntries = (IMG_UINT32)((uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift);
+
+	/* find the index/offset in PD entries  */
+	ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+	/* set the base PT info */
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+	/* find the index/offset of the first PT entry in the first PT page */
+	ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+	/* pdump the PT Page modification */
+	PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+	/* walk the PT pages, dumping as we go */
+	while(ui32NumPTEntries > 0)
+	{
+		MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
+
+		if(ui32NumPTEntries <= pMMUHeap->ui32PTNumEntriesUsable - ui32PTIndex)
+		{
+			ui32PTDumpCount = ui32NumPTEntries;
+		}
+		else
+		{
+			ui32PTDumpCount = pMMUHeap->ui32PTNumEntriesUsable - ui32PTIndex;
+		}
+
+		if (psPTInfo)
+		{
+#if defined(FIX_HW_BRN_31620)
+			IMG_UINT32 i;
+#endif
+			IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+			ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+			pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
+#if defined(FIX_HW_BRN_31620)
+			if ((ui32PDIndex % (BRN31620_PDE_CACHE_FILL_SIZE/BRN31620_PT_ADDRESS_RANGE_SIZE)) == BRN31620_DUMMY_PDE_INDEX)
+			{
+				for (i=ui32PTIndex;i<(ui32PTIndex + ui32PTDumpCount);i++)
+				{
+					if (pui32PTEntry[i] == ((psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+											| SGX_MMU_PTE_DUMMY_PAGE
+											| SGX_MMU_PTE_READONLY
+											| SGX_MMU_PTE_VALID))
+					{
+						PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[i], sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+					}
+					else
+					{
+						PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[i], sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+					}
+				}
+			}
+			else
+#endif
+			{
+				PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+			}
+		}
+
+		/* decrement PT entries left */
+		ui32NumPTEntries -= ui32PTDumpCount;
+
+		/* reset offset in page */
+		ui32PTIndex = 0;
+
+#if defined(FIX_HW_BRN_31620)
+		/* For 31620 we need to know which PD index we're working on */
+		ui32PDIndex++;
+#endif
+	}
+
+	PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
+}
+#endif /* #if defined(PDUMP) */
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_MapPage
+
+	PURPOSE:    Create a mapping for one page at a specified virtual address.
+
+	PARAMETERS: In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  DevPAddr - the device physical address of the page to map.
+	            In:  ui32MemFlags - BM r/w/cache flags
+	RETURNS:    None
+******************************************************************************/
+static IMG_VOID
+MMU_MapPage (MMU_HEAP *pMMUHeap,
+			 IMG_DEV_VIRTADDR DevVAddr,
+			 IMG_DEV_PHYADDR DevPAddr,
+			 IMG_UINT32 ui32MemFlags)
+{
+	IMG_UINT32 ui32Index;
+	IMG_UINT32 *pui32Tmp;
+	IMG_UINT32 ui32MMUFlags = 0;
+	MMU_PT_INFO **ppsPTInfoList;
+
+	/* check the physical alignment of the memory to map */
+	PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+	/*
+		unravel the read/write/cache flags
+	*/
+	if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
+	{
+		/* read/write */
+		ui32MMUFlags = 0;
+	}
+	else if(PVRSRV_MEM_READ & ui32MemFlags)
+	{
+		/* read only */
+		ui32MMUFlags |= SGX_MMU_PTE_READONLY;
+	}
+	else if(PVRSRV_MEM_WRITE & ui32MemFlags)
+	{
+		/* write only */
+		ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
+	}
+
+	/* cache coherency */
+	if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
+	{
+		ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
+	}
+
+#if !defined(FIX_HW_BRN_25503)
+	/* EDM protection */
+	if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
+	{
+		ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
+	}
+#endif
+
+	/*
+		we receive a device physical address for the page that is to be mapped
+		and a device virtual address representing where it should be mapped to
+	*/
+
+	/* find the index/offset in PD entries  */
+	ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+	/* and advance to the first PT info list */
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+	CheckPT(ppsPTInfoList[0]);
+
+	/* find the index/offset of the first PT in the first PT page */
+	ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+	/* setup pointer to the first entry in the PT page */
+	pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+	{
+		IMG_UINT32 uTmp = pui32Tmp[ui32Index];
+		
+		/* Is the current page already valid? (should not be unless it was allocated and not deallocated) */
+#if defined(FIX_HW_BRN_31620)
+		if ((uTmp & SGX_MMU_PTE_VALID) && ((DevVAddr.uiAddr & BRN31620_PDE_CACHE_FILL_MASK) != BRN31620_DUMMY_PAGE_OFFSET))
+#else
+ 		if ((uTmp & SGX_MMU_PTE_VALID) != 0)
+#endif
+
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08X PDIdx:%u PTIdx:%u",
+									DevVAddr.uiAddr,
+									DevVAddr.uiAddr >> pMMUHeap->ui32PDShift,
+									ui32Index ));
+			PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp));
+
+			PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x" DEVPADDR_FMT,
+						DevPAddr.uiAddr));
+
+#if PT_DUMP
+			DumpPT(ppsPTInfoList[0]);
+#endif
+		}
+#if !defined(FIX_HW_BRN_31620)
+		PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0);
+#endif
+	}
+#endif
+
+	/* One more valid entry in the page table. */
+	ppsPTInfoList[0]->ui32ValidPTECount++;
+
+	MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+	/* map in the physical page */
+	pui32Tmp[ui32Index] = ((IMG_UINT32)(DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+						& ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
+						| SGX_MMU_PTE_VALID
+						| ui32MMUFlags;
+	MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
+	CheckPT(ppsPTInfoList[0]);
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_MapScatter
+
+	PURPOSE:    Create a linear mapping for a range of pages at a specified
+	            virtual address.
+
+	PARAMETERS: In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  psSysAddr - the device physical address of the page to
+	                 map.
+	            In:  uSize - size of memory range in bytes
+                In:  ui32MemFlags - page table flags.
+	            In:  hUniqueTag - A unique ID for use as a tag identifier
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+				IMG_DEV_VIRTADDR DevVAddr,
+				IMG_SYS_PHYADDR *psSysAddr,
+				IMG_SIZE_T uSize,
+				IMG_UINT32 ui32MemFlags,
+				IMG_HANDLE hUniqueTag)
+{
+#if defined(PDUMP)
+	IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif /*PDUMP*/
+	IMG_UINT32 uCount, i, j;
+	IMG_UINT32 ui32NumDevicePages;
+	IMG_DEV_PHYADDR DevPAddr;
+
+	PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+#if defined(PDUMP)
+	MapBaseDevVAddr = DevVAddr;
+#else
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif /*PDUMP*/
+
+	PVR_ASSERT((HOST_PAGESIZE() % pMMUHeap->ui32DataPageSize) == 0);
+
+	ui32NumDevicePages = HOST_PAGESIZE() / pMMUHeap->ui32DataPageSize;
+
+	for (i=0, uCount=0; uCount<uSize; i++, uCount+=HOST_PAGESIZE())
+	{
+		IMG_SYS_PHYADDR sSysAddr;
+
+		sSysAddr = psSysAddr[i];
+
+
+		/* check the physical alignment of the memory to map */
+		PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+		for(j=0; j< ui32NumDevicePages; j++)
+		{
+			DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+			MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+
+			PVR_DPF ((PVR_DBG_MESSAGE,
+						"MMU_MapScatter: devVAddr=%x, SysAddr=" SYSPADDR_FMT ", size=0x%x/0x%" SIZE_T_FMT_LEN "x",
+						DevVAddr.uiAddr, sSysAddr.uiAddr, (uCount + j*pMMUHeap->ui32DataPageSize), uSize));
+
+			DevVAddr.uiAddr += pMMUHeap->ui32DataPageSize;
+			sSysAddr.uiAddr += pMMUHeap->ui32DataPageSize;
+		}
+	}
+
+#if (SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE > 1)
+	MMU_InvalidatePageTableCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_MapPages
+
+	PURPOSE:    Create a linear mapping for a ranege of pages at a specified
+	            virtual address.
+
+	PARAMETERS: In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  SysPAddr - the system physical address of the page to
+	                 map.
+	            In:  uSize - size of memory range in bytes
+                In:  ui32MemFlags - page table flags.
+	            In:  hUniqueTag - A unique ID for use as a tag identifier
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+			  IMG_DEV_VIRTADDR DevVAddr,
+			  IMG_SYS_PHYADDR SysPAddr,
+			  IMG_SIZE_T uSize,
+			  IMG_UINT32 ui32MemFlags,
+			  IMG_HANDLE hUniqueTag)
+{
+	IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+	IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif /*PDUMP*/
+	IMG_UINT32 uCount;
+	IMG_UINT32 ui32VAdvance;
+	IMG_UINT32 ui32PAdvance;
+
+	PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPages: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=" SYSPADDR_FMT ", size=0x%" SIZE_T_FMT_LEN "x",
+								pMMUHeap->psDevArena->pszName,
+								pMMUHeap->psDevArena->ui32HeapID,
+								DevVAddr.uiAddr, 
+								SysPAddr.uiAddr,
+								uSize));
+
+	/* set the virtual and physical advance */
+	ui32VAdvance = pMMUHeap->ui32DataPageSize;
+	ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+	MapBaseDevVAddr = DevVAddr;
+#else
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif /*PDUMP*/
+
+	DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+	/* check the physical alignment of the memory to map */
+	PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+	/*
+		for dummy allocations there is only one physical
+		page backing the virtual range
+	*/
+	if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+	{
+		ui32PAdvance = 0;
+	}
+
+	for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+	{
+		MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+		DevVAddr.uiAddr += ui32VAdvance;
+		DevPAddr.uiAddr += ui32PAdvance;
+	}
+
+#if (SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE > 1)
+	MMU_InvalidatePageTableCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_MapPagesSparse
+
+	PURPOSE:    Create a linear mapping for a ranege of pages at a specified
+	            virtual address.
+
+	PARAMETERS: In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  SysPAddr - the system physical address of the page to
+	                 map.
+				In:  ui32ChunkSize - Size of the chunk (must be page multiple)
+				In:  ui32NumVirtChunks - Number of virtual chunks
+				In:  ui32NumPhysChunks - Number of physical chunks
+				In:  pabMapChunk - Mapping array
+                In:  ui32MemFlags - page table flags.
+	            In:  hUniqueTag - A unique ID for use as a tag identifier
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+MMU_MapPagesSparse (MMU_HEAP *pMMUHeap,
+					IMG_DEV_VIRTADDR DevVAddr,
+					IMG_SYS_PHYADDR SysPAddr,
+					IMG_UINT32 ui32ChunkSize,
+					IMG_UINT32 ui32NumVirtChunks,
+					IMG_UINT32 ui32NumPhysChunks,
+					IMG_BOOL *pabMapChunk,
+					IMG_UINT32 ui32MemFlags,
+					IMG_HANDLE hUniqueTag)
+{
+	IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+	IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif /*PDUMP*/
+	IMG_UINT32 uCount;
+	IMG_UINT32 ui32VAdvance;
+	IMG_UINT32 ui32PAdvance;
+	IMG_SIZE_T uSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+#if !defined(PVRSRV_NEED_PVR_DPF)
+	PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+#endif
+
+	PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+	PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPagesSparse: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=" SYSPADDR_FMT ", VM space=0x%" SIZE_T_FMT_LEN "x, PHYS space=0x%x",
+								pMMUHeap->psDevArena->pszName,
+								pMMUHeap->psDevArena->ui32HeapID,
+								DevVAddr.uiAddr, 
+								SysPAddr.uiAddr,
+								uSizeVM,
+								ui32ChunkSize * ui32NumPhysChunks));
+
+	/* set the virtual and physical advance */
+	ui32VAdvance = pMMUHeap->ui32DataPageSize;
+	ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+	MapBaseDevVAddr = DevVAddr;
+#else
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif /*PDUMP*/
+
+	DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+	/* check the physical alignment of the memory to map */
+	PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+	/*
+		for dummy allocations there is only one physical
+		page backing the virtual range
+	*/
+	if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+	{
+		ui32PAdvance = 0;
+	}
+
+	for (uCount=0; uCount<uSizeVM; uCount+=ui32VAdvance)
+	{
+		if (pabMapChunk[uCount/ui32ChunkSize])
+		{
+			MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+			DevPAddr.uiAddr += ui32PAdvance;
+		}
+		DevVAddr.uiAddr += ui32VAdvance;
+	}
+	pMMUHeap->bHasSparseMappings = IMG_TRUE;
+
+#if (SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE > 1)
+	MMU_InvalidatePageTableCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSizeVM, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_MapShadow
+
+	PURPOSE:    Create a mapping for a range of pages from either a CPU
+				virtual adddress, (or if NULL a hOSMemHandle) to a specified
+				device virtual address.
+
+	PARAMETERS: In:  pMMUHeap - the mmu.
+                In:  MapBaseDevVAddr - A page aligned device virtual address
+                                       to start mapping from.
+                In:  uByteSize - A page aligned mapping length in bytes.
+                In:  CpuVAddr - A page aligned CPU virtual address.
+                In:  hOSMemHandle - An alternative OS specific memory handle
+                                    for mapping RAM without a CPU virtual
+                                    address
+                Out: pDevVAddr - deprecated - It used to return a byte aligned
+                                 device virtual address corresponding to the
+                                 cpu virtual address (When CpuVAddr wasn't
+                                 constrained to be page aligned.) Now it just
+                                 returns MapBaseDevVAddr. Unaligned semantics
+                                 can easily be handled above this API if required.
+                In: hUniqueTag - A unique ID for use as a tag identifier
+                In: ui32MemFlags - page table flags.
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadow (MMU_HEAP          *pMMUHeap,
+			   IMG_DEV_VIRTADDR   MapBaseDevVAddr,
+			   IMG_SIZE_T         uByteSize,
+			   IMG_CPU_VIRTADDR   CpuVAddr,
+			   IMG_HANDLE         hOSMemHandle,
+			   IMG_DEV_VIRTADDR  *pDevVAddr,
+			   IMG_UINT32         ui32MemFlags,
+			   IMG_HANDLE         hUniqueTag)
+{
+	IMG_UINT32			i;
+	IMG_UINT32			uOffset = 0;
+	IMG_DEV_VIRTADDR	MapDevVAddr;
+	IMG_UINT32			ui32VAdvance;
+	IMG_UINT32			ui32PAdvance;
+
+#if !defined (PDUMP)
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"MMU_MapShadow: DevVAddr:%08X, Bytes:0x%" SIZE_T_FMT_LEN "x, CPUVAddr:%p",
+			MapBaseDevVAddr.uiAddr,
+			uByteSize,
+			CpuVAddr));
+
+	/* set the virtual and physical advance */
+	ui32VAdvance = pMMUHeap->ui32DataPageSize;
+	ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+	/* note: can't do useful check on the CPU Addr other than it being at least 4k alignment */
+	PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+	PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
+	pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+	/*
+		for dummy allocations there is only one physical
+		page backing the virtual range
+	*/
+	if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+	{
+		ui32PAdvance = 0;
+	}
+
+	/* Loop through cpu memory and map page by page */
+	MapDevVAddr = MapBaseDevVAddr;
+	for (i=0; i<uByteSize; i+=ui32VAdvance)
+	{
+		IMG_CPU_PHYADDR CpuPAddr;
+		IMG_DEV_PHYADDR DevPAddr;
+
+		if(CpuVAddr)
+		{
+			CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle,
+										  (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset));
+		}
+		else
+		{
+			CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+		}
+		DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+		/* check the physical alignment of the memory to map */
+		PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+		PVR_DPF ((PVR_DBG_MESSAGE,
+				"Offset=0x%x: CpuVAddr=%p, CpuPAddr=" CPUPADDR_FMT ", DevVAddr=%08X, DevPAddr=" DEVPADDR_FMT,
+				uOffset,
+				(IMG_PVOID)((IMG_UINTPTR_T)CpuVAddr + uOffset),
+				CpuPAddr.uiAddr,
+				MapDevVAddr.uiAddr,
+				DevPAddr.uiAddr));
+
+		MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+
+		/* loop update */
+		MapDevVAddr.uiAddr += ui32VAdvance;
+		uOffset += ui32PAdvance;
+	}
+
+#if (SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE > 1)
+	MMU_InvalidatePageTableCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_MapShadowSparse
+
+	PURPOSE:    Create a mapping for a range of pages from either a CPU
+				virtual adddress, (or if NULL a hOSMemHandle) to a specified
+				device virtual address.
+
+	PARAMETERS: In:  pMMUHeap - the mmu.
+                In:  MapBaseDevVAddr - A page aligned device virtual address
+                                       to start mapping from.
+				In:  ui32ChunkSize - Size of the chunk (must be page multiple)
+				In:  ui32NumVirtChunks - Number of virtual chunks
+				In:  ui32NumPhysChunks - Number of physical chunks
+				In:  pabMapChunk - Mapping array
+                In:  CpuVAddr - A page aligned CPU virtual address.
+                In:  hOSMemHandle - An alternative OS specific memory handle
+                                    for mapping RAM without a CPU virtual
+                                    address
+                Out: pDevVAddr - deprecated - It used to return a byte aligned
+                                 device virtual address corresponding to the
+                                 cpu virtual address (When CpuVAddr wasn't
+                                 constrained to be page aligned.) Now it just
+                                 returns MapBaseDevVAddr. Unaligned semantics
+                                 can easily be handled above this API if required.
+                In: hUniqueTag - A unique ID for use as a tag identifier
+                In: ui32MemFlags - page table flags.
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadowSparse (MMU_HEAP          *pMMUHeap,
+					 IMG_DEV_VIRTADDR   MapBaseDevVAddr,
+					 IMG_UINT32         ui32ChunkSize,
+					 IMG_UINT32         ui32NumVirtChunks,
+					 IMG_UINT32         ui32NumPhysChunks,
+					 IMG_BOOL          *pabMapChunk,
+					 IMG_CPU_VIRTADDR   CpuVAddr,
+					 IMG_HANDLE         hOSMemHandle,
+					 IMG_DEV_VIRTADDR  *pDevVAddr,
+					 IMG_UINT32         ui32MemFlags,
+					 IMG_HANDLE         hUniqueTag)
+{
+	IMG_UINT32			i;
+	IMG_UINT32			uOffset = 0;
+	IMG_DEV_VIRTADDR	MapDevVAddr;
+	IMG_UINT32			ui32VAdvance;
+	IMG_UINT32			ui32PAdvance;
+	IMG_SIZE_T			uiSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+	IMG_UINT32			ui32ChunkIndex = 0;
+	IMG_UINT32			ui32ChunkOffset = 0;
+#if !defined(PVRSRV_NEED_PVR_DPF)
+	PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+#endif
+#if !defined (PDUMP)
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+	PVR_DPF ((PVR_DBG_MESSAGE,
+			"MMU_MapShadowSparse: DevVAddr:%08X, VM space:0x%" SIZE_T_FMT_LEN "x, CPUVAddr:%p PHYS space:0x%x",
+			MapBaseDevVAddr.uiAddr,
+			uiSizeVM,
+			CpuVAddr,
+			ui32ChunkSize * ui32NumPhysChunks));
+
+	/* set the virtual and physical advance */
+	ui32VAdvance = pMMUHeap->ui32DataPageSize;
+	ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+	/* note: can't do useful check on the CPU Addr other than it being at least 4k alignment */
+	PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+	PVR_ASSERT(((IMG_UINT32)uiSizeVM & pMMUHeap->ui32DataPageMask) == 0);
+	pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+	/* Shouldn't come through the sparse interface */
+	PVR_ASSERT((ui32MemFlags & PVRSRV_MEM_DUMMY) == 0);
+
+	/* Loop through cpu memory and map page by page */
+	MapDevVAddr = MapBaseDevVAddr;
+	for (i=0; i<uiSizeVM; i+=ui32VAdvance)
+	{
+		IMG_CPU_PHYADDR CpuPAddr;
+		IMG_DEV_PHYADDR DevPAddr;
+
+		if (pabMapChunk[i/ui32ChunkSize])
+		/*if (pabMapChunk[ui32ChunkIndex])*/
+		{
+			if(CpuVAddr)
+			{
+				CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle,
+											  (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset));
+			}
+			else
+			{
+				CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+			}
+			DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+	
+			/* check the physical alignment of the memory to map */
+			PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+	
+			PVR_DPF ((PVR_DBG_MESSAGE,
+					"Offset=0x%x: CpuVAddr=%p, CpuPAddr=" CPUPADDR_FMT ", DevVAddr=%08X, DevPAddr=" DEVPADDR_FMT,
+					uOffset,
+					(void *)((IMG_UINTPTR_T)CpuVAddr + uOffset),
+					CpuPAddr.uiAddr,
+					MapDevVAddr.uiAddr,
+					DevPAddr.uiAddr));
+	
+			MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+			uOffset += ui32PAdvance;
+		}
+
+		/* loop update */
+		MapDevVAddr.uiAddr += ui32VAdvance;
+
+		if (ui32ChunkOffset == ui32ChunkSize)
+		{
+			ui32ChunkIndex++;
+			ui32ChunkOffset = 0;
+		}
+	}
+
+	pMMUHeap->bHasSparseMappings = IMG_TRUE;
+
+#if (SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE > 1)
+	MMU_InvalidatePageTableCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uiSizeVM, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_UnmapPages
+
+	PURPOSE:    unmap pages and invalidate virtual address
+
+	PARAMETERS:	In:  psMMUHeap - the mmu.
+	            In:  sDevVAddr - the device virtual address.
+	            In:  ui32PageCount - page count
+	            In:  hUniqueTag - A unique ID for use as a tag identifier
+
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+				IMG_DEV_VIRTADDR sDevVAddr,
+				IMG_UINT32 ui32PageCount,
+				IMG_HANDLE hUniqueTag)
+{
+	IMG_UINT32			uPageSize = psMMUHeap->ui32DataPageSize;
+	IMG_DEV_VIRTADDR	sTmpDevVAddr;
+	IMG_UINT32			i;
+	IMG_UINT32			ui32PDIndex;
+	IMG_UINT32			ui32PTIndex;
+	IMG_UINT32			*pui32Tmp;
+
+#if !defined (PDUMP)
+	PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+	/* setup tmp devvaddr to base of allocation */
+	sTmpDevVAddr = sDevVAddr;
+
+	for(i=0; i<ui32PageCount; i++)
+	{
+		MMU_PT_INFO **ppsPTInfoList;
+
+		/* find the index/offset in PD entries  */
+		ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+		/* and advance to the first PT info list */
+		ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+		/* find the index/offset of the first PT in the first PT page */
+		ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+		/* Is the PT page valid? */
+		if ((!ppsPTInfoList[0]) && (!psMMUHeap->bHasSparseMappings))
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+									sTmpDevVAddr.uiAddr,
+									sDevVAddr.uiAddr,
+									i,
+									ui32PDIndex,
+									ui32PTIndex));
+
+			/* advance the sTmpDevVAddr by one page */
+			sTmpDevVAddr.uiAddr += uPageSize;
+
+			/* Try to unmap the remaining allocation pages */
+			continue;
+		}
+
+		CheckPT(ppsPTInfoList[0]);
+
+		/* setup pointer to the first entry in the PT page */
+		pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+		/* Decrement the valid page count only if the current page is valid*/
+		if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+		{
+			ppsPTInfoList[0]->ui32ValidPTECount--;
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+									sTmpDevVAddr.uiAddr,
+									sDevVAddr.uiAddr,
+									i,
+									ui32PDIndex,
+									ui32PTIndex));
+			PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08X", pui32Tmp[ui32PTIndex]));
+		}
+
+		/* The page table count should not go below zero */
+		PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+		MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+		/* point the PT entry to the dummy data page */
+		pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+								| SGX_MMU_PTE_VALID;
+#else
+		/* invalidate entry */
+#if defined(FIX_HW_BRN_31620)
+		BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
+#else
+		pui32Tmp[ui32PTIndex] = 0;
+#endif
+#endif
+		MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
+
+		CheckPT(ppsPTInfoList[0]);
+
+		/* advance the sTmpDevVAddr by one page */
+		sTmpDevVAddr.uiAddr += uPageSize;
+	}
+
+	MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+
+#if defined(PDUMP)
+	MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_GetPhysPageAddr
+
+	PURPOSE:    extracts physical address from MMU page tables
+
+	PARAMETERS: In:  pMMUHeap - the mmu
+	PARAMETERS: In:  sDevVPageAddr - the virtual address to extract physical
+					page mapping from
+	RETURNS:    None
+******************************************************************************/
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
+{
+	IMG_UINT32 *pui32PageTable;
+	IMG_UINT32 ui32Index;
+	IMG_DEV_PHYADDR sDevPAddr;
+	MMU_PT_INFO **ppsPTInfoList;
+
+	/* find the index/offset in PD entries  */
+	ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+	/* and advance to the first PT info list */
+	ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+	if (!ppsPTInfoList[0])
+	{
+		/* Heaps with sparse mappings are allowed invalid pages */
+		if (!pMMUHeap->bHasSparseMappings)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+		}
+		sDevPAddr.uiAddr = 0;
+		return sDevPAddr;
+	}
+
+	/* find the index/offset of the first PT in the first PT page */
+	ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+	/* setup pointer to the first entry in the PT page */
+	pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+	/* read back physical page */
+	sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+	/* Mask off non-address bits */
+	sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+	/* and align the address */
+	sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+	return sDevPAddr;
+}
+
+
+IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext)
+{
+	return (pMMUContext->sPDDevPAddr);
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   SGXGetPhysPageAddr
+
+	PURPOSE:    Gets DEV and CPU physical address of sDevVAddr
+
+	PARAMETERS: In:  hDevMemHeap - device mem heap handle
+	PARAMETERS: In:  sDevVAddr - the base virtual address to unmap from
+	PARAMETERS: Out: pDevPAddr - DEV physical address
+	PARAMETERS: Out: pCpuPAddr - CPU physical address
+	RETURNS:    None
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
+								   IMG_DEV_VIRTADDR sDevVAddr,
+								   IMG_DEV_PHYADDR *pDevPAddr,
+								   IMG_CPU_PHYADDR *pCpuPAddr)
+{
+	MMU_HEAP *pMMUHeap;
+	IMG_DEV_PHYADDR DevPAddr;
+
+	/*
+		Get MMU Heap From hDevMemHeap
+	*/
+	pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
+
+	DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
+	pCpuPAddr->uiAddr = DevPAddr.uiAddr; /* SysDevPAddrToCPUPAddr(DevPAddr) */
+	pDevPAddr->uiAddr = DevPAddr.uiAddr;
+
+	return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+/*!
+******************************************************************************
+    FUNCTION:   SGXGetMMUPDAddrKM
+
+    PURPOSE:    Gets PD device physical address of hDevMemContext
+
+    PARAMETERS: In:  hDevCookie - device cookie
+	PARAMETERS: In:  hDevMemContext - memory context
+	PARAMETERS: Out: psPDDevPAddr - MMU PD address
+    RETURNS:    None
+******************************************************************************/
+PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE		hDevCookie,
+								IMG_HANDLE 		hDevMemContext,
+								IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+	if (!hDevCookie || !hDevMemContext || !psPDDevPAddr)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* return the address */
+	*psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_BIFResetPDAlloc
+
+	PURPOSE:    Allocate a dummy Page Directory, Page Table and Page which can
+				be used for dynamic dummy page mapping during SGX reset.
+				Note: since this is only used for hardware recovery, no
+				pdumping is performed.
+
+	PARAMETERS: In:  psDevInfo - device info
+	RETURNS:    PVRSRV_OK or error
+******************************************************************************/
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	PVRSRV_ERROR eError;
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	IMG_HANDLE hOSMemHandle = IMG_NULL;
+	IMG_BYTE *pui8MemBlock = IMG_NULL;
+	IMG_SYS_PHYADDR sMemBlockSysPAddr;
+	IMG_CPU_PHYADDR sMemBlockCpuPAddr;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+	/* allocate 3 pages - for the PD, PT and dummy page */
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+		/* UMA system */
+		eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+						      3 * SGX_MMU_PAGE_SIZE,
+						      SGX_MMU_PAGE_SIZE,
+							  IMG_NULL,
+							  0,
+							  IMG_NULL,
+						      (IMG_VOID **)&pui8MemBlock,
+						      &hOSMemHandle);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to OSAllocPages failed"));
+			return eError;
+		}
+
+		/* translate address to device physical */
+		if(pui8MemBlock)
+		{
+			sMemBlockCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle,
+												  pui8MemBlock);
+		}
+		else
+		{
+			/* This isn't used in all cases since not all ports currently support
+			 * OSMemHandleToCpuPAddr() */
+			sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
+		}
+	}
+	else
+	{
+		/* non-UMA system */
+
+		/* 
+		   We cannot use IMG_SYS_PHYADDR here, as that is 64-bit for 32-bit PAE builds.
+		   The physical address in this call to RA_Alloc is specifically the SysPAddr 
+		   of local (card) space, and it is highly unlikely we would ever need to 
+		   support > 4GB of local (card) memory (this does assume that such local
+		   memory will be mapped into System physical memory space at a low address so
+		   that any and all local memory exists within the 4GB SYSPAddr range).
+		 */
+		IMG_UINTPTR_T uiLocalPAddr;
+
+		if(RA_Alloc(psLocalDevMemArena,
+					3 * SGX_MMU_PAGE_SIZE,
+					IMG_NULL,
+					IMG_NULL,
+					0,
+					SGX_MMU_PAGE_SIZE,
+					0,
+					IMG_NULL,
+					0,
+					&uiLocalPAddr) != IMG_TRUE)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+
+		/* Munge the local PAddr back into the SysPAddr */
+		sMemBlockSysPAddr.uiAddr = uiLocalPAddr;
+
+		/* derive the CPU virtual address */
+		sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
+		pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
+									  SGX_MMU_PAGE_SIZE * 3,
+									  PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+									  &hOSMemHandle);
+		if(!pui8MemBlock)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR failed to map page tables"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+	}
+
+	PVR_ASSERT(pui8MemBlock != IMG_NULL);
+
+	psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle;
+	psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
+	psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+	psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+	/* override pointer cast warnings */
+	/* PRQA S 3305,509 2 */
+	psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
+	psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
+
+	/* Invalidate entire PD and PT. */
+	OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
+	OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
+	/* Fill dummy page with markers. */
+	OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_BIFResetPDFree
+
+	PURPOSE:    Free resources allocated in MMU_BIFResetPDAlloc.
+
+	PARAMETERS: In:  psDevInfo - device info
+	RETURNS:
+******************************************************************************/
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	IMG_SYS_PHYADDR sPDSysPAddr;
+
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+	/* free the page directory */
+	if(psLocalDevMemArena == IMG_NULL)
+	{
+		OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+					3 * SGX_MMU_PAGE_SIZE,
+					psDevInfo->pui32BIFResetPD,
+					psDevInfo->hBIFResetPDOSMemHandle);
+	}
+	else
+	{
+		OSUnMapPhysToLin(psDevInfo->pui32BIFResetPD,
+                         3 * SGX_MMU_PAGE_SIZE,
+                         PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+                         psDevInfo->hBIFResetPDOSMemHandle);
+
+		sPDSysPAddr = SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->sBIFResetPDDevPAddr);
+		/* Note that the cast to IMG_UINTPTR_T is ok as we're local mem. */
+		RA_Free(psLocalDevMemArena, (IMG_UINTPTR_T)sPDSysPAddr.uiAddr, IMG_FALSE);
+	}
+}
+
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32FaultAddr)
+{
+	MMU_CONTEXT *psMMUContext = psDevInfo->pvMMUContextList;
+
+	while (psMMUContext && (psMMUContext->sPDDevPAddr.uiAddr != ui32PDDevPAddr))
+	{
+		psMMUContext = psMMUContext->psNext;
+	}
+
+	if (psMMUContext)
+	{
+		IMG_UINT32 ui32PTIndex;
+		IMG_UINT32 ui32PDIndex;
+
+		PVR_LOG(("Found MMU context for page fault 0x%08x", ui32FaultAddr));
+		PVR_LOG(("GPU memory context is for PID=%d (%s)", psMMUContext->ui32PID, psMMUContext->szName));
+
+		ui32PTIndex = (ui32FaultAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+		ui32PDIndex = (ui32FaultAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PT_SHIFT + SGX_MMU_PAGE_SHIFT);
+
+		if (psMMUContext->apsPTInfoList[ui32PDIndex])
+		{
+			if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+			{
+				IMG_UINT32 *pui32Ptr = psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+				IMG_UINT32 ui32PTE = pui32Ptr[ui32PTIndex];
+
+				PVR_LOG(("PDE valid: PTE = 0x%08x (PhysAddr = 0x%08x, %s)",
+						  ui32PTE,
+						  ui32PTE & SGX_MMU_PTE_ADDR_MASK,
+						  ui32PTE & SGX_MMU_PTE_VALID?"valid":"Invalid"));
+			}
+			else
+			{
+				PVR_LOG(("Found PT info but no CPU address"));
+			}
+		}
+		else
+		{
+			PVR_LOG(("No PDE found"));
+		}
+	}
+}
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*!
+******************************************************************************
+	FUNCTION:   MMU_MapExtSystemCacheRegs
+
+	PURPOSE:    maps external system cache control registers into SGX MMU
+
+	PARAMETERS: In:  psDeviceNode - device node
+	RETURNS:
+******************************************************************************/
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	IMG_UINT32 *pui32PT;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 ui32PTIndex;
+	PDUMP_MMU_ATTRIB sMMUAttrib;
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+	sMMUAttrib = psDevInfo->sMMUAttrib;
+#if defined(PDUMP)
+	MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+						SGX_MMU_PAGE_MASK,
+						SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+#if defined(PDUMP)
+	{
+		IMG_CHAR		szScript[128];
+
+		sprintf(szScript, "MALLOC :EXTSYSCACHE:PA_%08X%08X %u %u 0x%p\r\n", 0, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr, SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr);
+		PDumpOSWriteString2(szScript, PDUMP_FLAGS_CONTINUOUS);
+	}
+#endif
+
+	ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+	ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+	pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+
+	MakeKernelPageReadWrite(pui32PT);
+	/* map the PT to the registers */
+	pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+							| SGX_MMU_PTE_VALID;
+	MakeKernelPageReadOnly(pui32PT);
+#if defined(PDUMP)
+	/* Add the entery to the PT */
+	{
+		IMG_DEV_PHYADDR sDevPAddr;
+		IMG_CPU_PHYADDR sCpuPAddr;
+		IMG_UINT32 ui32PageMask;
+		IMG_UINT32 ui32PTE;
+		PVRSRV_ERROR eErr;
+
+		PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+		ui32PageMask = sMMUAttrib.ui32PTSize - 1;
+		sCpuPAddr = OSMapLinToCPUPhys(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->hPTPageOSMemHandle, &pui32PT[ui32PTIndex]);
+		sDevPAddr = SysCpuPAddrToDevPAddr(sMMUAttrib.sDevId.eDeviceType, sCpuPAddr);
+		ui32PTE = *((IMG_UINT32 *) (&pui32PT[ui32PTIndex]));
+
+		eErr = PDumpOSBufprintf(hScript,
+								ui32MaxLenScript,
+								"WRW :%s:PA_%p%p:0x%08X :%s:PA_%p%08X:0x%08X\r\n",
+								sMMUAttrib.sDevId.pszPDumpDevName,
+								PDUMP_PT_UNIQUETAG,
+								(IMG_PVOID)((sDevPAddr.uiAddr) & ~ui32PageMask),
+								(sDevPAddr.uiAddr) & ui32PageMask,
+								"EXTSYSCACHE",
+								PDUMP_PD_UNIQUETAG,
+								(ui32PTE & sMMUAttrib.ui32PDEMask) << sMMUAttrib.ui32PTEAlignShift,
+								ui32PTE & ~sMMUAttrib.ui32PDEMask);
+					if(eErr != PVRSRV_OK)
+					{
+						return eErr;
+					}
+					PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+	}
+#endif
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+	FUNCTION:   MMU_UnmapExtSystemCacheRegs
+
+	PURPOSE:    unmaps external system cache control registers
+
+	PARAMETERS: In:  psDeviceNode - device node
+	RETURNS:
+******************************************************************************/
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	SYS_DATA *psSysData;
+	RA_ARENA *psLocalDevMemArena;
+	PVRSRV_SGXDEV_INFO *psDevInfo;
+	IMG_UINT32 ui32PDIndex;
+	IMG_UINT32 ui32PTIndex;
+	IMG_UINT32 *pui32PT;
+	PDUMP_MMU_ATTRIB sMMUAttrib;
+
+	psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+	sMMUAttrib = psDevInfo->sMMUAttrib;
+
+#if defined(PDUMP)
+	MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+						SGX_MMU_PAGE_MASK,
+						SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+	SysAcquireData(&psSysData);
+
+	psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+	/* unmap the MMU page table from the PD */
+	ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+	ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+	/* Only unmap it if the PT hasn't already been freed */
+	if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex])
+	{
+		if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+		{
+			pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+		}
+	}
+
+	MakeKernelPageReadWrite(pui32PT);
+	pui32PT[ui32PTIndex] = 0;
+	MakeKernelPageReadOnly(pui32PT);
+
+	PDUMPMEMPTENTRIES(&sMMUAttrib, psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->hPDOSMemHandle, &pui32PT[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+	return PVRSRV_OK;
+}
+#endif
+
+
+#if PAGE_TEST
+/*!
+******************************************************************************
+	FUNCTION:   PageTest
+
+	PURPOSE:    Tests page table memory, for use during device bring-up.
+
+	PARAMETERS: In:  void* pMem - page address (CPU mapped)
+	PARAMETERS: In:  IMG_DEV_PHYADDR sDevPAddr - page device phys address
+	RETURNS:    None, provides debug output and breaks if an error is detected.
+******************************************************************************/
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
+{
+	volatile IMG_UINT32 ui32WriteData;
+	volatile IMG_UINT32 ui32ReadData;
+	volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem;
+	IMG_INT n;
+	IMG_BOOL bOK=IMG_TRUE;
+
+	ui32WriteData = 0xffffffff;
+
+	for (n=0; n<1024; n++)
+	{
+		pMem32[n] = ui32WriteData;
+		ui32ReadData = pMem32[n];
+
+		if (ui32WriteData != ui32ReadData)
+		{
+			// Mem fault
+			PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x" DEVPADDR_FMT, sDevPAddr.uiAddr + (n<<2) ));
+			PVR_DBG_BREAK;
+			bOK = IMG_FALSE;
+		}
+ 	}
+
+	ui32WriteData = 0;
+
+	for (n=0; n<1024; n++)
+	{
+		pMem32[n] = ui32WriteData;
+		ui32ReadData = pMem32[n];
+
+		if (ui32WriteData != ui32ReadData)
+		{
+			// Mem fault
+			PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x" DEVPADDR_FMT, sDevPAddr.uiAddr + (n<<2)));
+			PVR_DBG_BREAK;
+			bOK = IMG_FALSE;
+		}
+ 	}
+
+	if (bOK)
+	{
+		PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x" DEVPADDR_FMT " is OK", sDevPAddr.uiAddr));
+	}
+	else
+	{
+		PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x" DEVPADDR_FMT " *** FAILED ***", sDevPAddr.uiAddr));
+	}
+}
+#endif
+
+/******************************************************************************
+ End of file (mmu.c)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/mmu.h b/drivers/gpu/pvr/services4/srvkm/devices/sgx/mmu.h
new file mode 100644
index 0000000..3c849fc
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/mmu.h
@@ -0,0 +1,501 @@
+/*************************************************************************/ /*!
+@Title          MMU Management
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements basic low level control of MMU.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _MMU_H_
+#define _MMU_H_
+
+#include "sgxinfokm.h"
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_Initialise
+
+	PURPOSE:    Initialise the mmu module.
+	                	
+	PARAMETERS:	None
+	RETURNS:	PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_Finalise
+
+	PURPOSE:    Finalise the mmu module, deallocate all resources.
+	                	
+	PARAMETERS:	None.
+	RETURNS:	None.
+******************************************************************************/
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext);
+
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_InsertHeap
+
+	PURPOSE:    Inserts shared heap into the specified context 
+				from the kernel context
+	                	
+	PARAMETERS:	None.
+	RETURNS:	None.
+******************************************************************************/
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+
+/*
+******************************************************************************
+    FUNCTION:   MMU_Create
+
+    PURPOSE:    Create an mmu device.
+
+    PARAMETERS: In: psMMUContext -
+                In: psDevArena - 
+				Out: ppsVMArena
+    RETURNS:	MMU_HEAP
+******************************************************************************/
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+			DEV_ARENA_DESCRIPTOR *psDevArena,
+			RA_ARENA **ppsVMArena,
+			PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_Delete
+
+	PURPOSE:    Delete an mmu device.
+	                	
+	PARAMETERS:	In:  pMMUHeap - The mmu to delete.
+	RETURNS:	
+******************************************************************************/
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap);
+
+/*
+******************************************************************************
+    FUNCTION:   MMU_Alloc
+    PURPOSE:    Allocate space in an mmu's virtual address space.
+    PARAMETERS:	In:  pMMUHeap - MMU to allocate on.
+                In:  uSize - Size in bytes to allocate.
+                Out: pActualSize - If non null receives actual size allocated. 
+                In:  uFlags - Allocation flags.
+                In:  uDevVAddrAlignment - Required alignment.
+                Out: pDevVAddr - Receives base address of allocation.
+    RETURNS:	IMG_TRUE - Success
+                IMG_FALSE - Failure
+******************************************************************************/
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+           IMG_SIZE_T uSize,
+           IMG_SIZE_T *pActualSize,
+           IMG_UINT32 uFlags,
+		   IMG_UINT32 uDevVAddrAlignment,
+           IMG_DEV_VIRTADDR *pDevVAddr);
+
+/*
+******************************************************************************
+    FUNCTION:   MMU_Free
+    PURPOSE:    Frees space in an mmu's virtual address space.
+    PARAMETERS:	In: pMMUHeap - MMU to free on.
+                In: DevVAddr - Base address of allocation.
+    RETURNS:	IMG_TRUE - Success
+                IMG_FALSE - Failure
+******************************************************************************/
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap,
+          IMG_DEV_VIRTADDR DevVAddr,
+		  IMG_UINT32 ui32Size);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_Enable
+
+	PURPOSE:    Enable an mmu. Establishes pages tables and takes the mmu out
+	            of bypass and waits for the mmu to acknowledge enabled.
+	                	
+	PARAMETERS:	In:  pMMUHeap - the mmu
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID 
+MMU_Enable (MMU_HEAP *pMMUHeap);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_Disable
+
+	PURPOSE:    Disable an mmu, takes the mmu into bypass.
+	                	
+	PARAMETERS:	In:  pMMUHeap - the mmu
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID 
+MMU_Disable (MMU_HEAP *pMMUHeap);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_MapPages
+
+	PURPOSE:    Create a mapping for a range of pages from a device physical
+                adddress to a specified device virtual address.
+
+	PARAMETERS:	In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  SysPAddr - the system physical address of the page to map.
+	            In:  uSize - size of memory range in bytes
+                In:  ui32MemFlags - page table flags.
+	            In:  hUniqueTag - A unique ID for use as a tag identifier 
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+			  IMG_DEV_VIRTADDR DevVAddr,
+			  IMG_SYS_PHYADDR SysPAddr,
+			  IMG_SIZE_T uSize,
+			  IMG_UINT32 ui32MemFlags,
+			  IMG_HANDLE hUniqueTag);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_MapPagesSparse
+
+	PURPOSE:    Create a mapping for a range of pages from a device physical
+                adddress to a specified device virtual address.
+
+	PARAMETERS:	In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  SysPAddr - the system physical address of the page to map.
+				In:  ui32ChunkSize - Size of the chunk (must be page multiple)
+				In:  ui32NumVirtChunks - Number of virtual chunks
+				In:  ui32NumPhysChunks - Number of physical chunks
+				In:  pabMapChunk - Mapping array
+                In:  ui32MemFlags - page table flags.
+	            In:  hUniqueTag - A unique ID for use as a tag identifier 
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_MapPagesSparse (MMU_HEAP *pMMUHeap,
+					IMG_DEV_VIRTADDR DevVAddr,
+					IMG_SYS_PHYADDR SysPAddr,
+					IMG_UINT32 ui32ChunkSize,
+					IMG_UINT32 ui32NumVirtChunks,
+					IMG_UINT32 ui32NumPhysChunks,
+					IMG_BOOL *pabMapChunk,
+					IMG_UINT32 ui32MemFlags,
+					IMG_HANDLE hUniqueTag);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_MapShadow
+
+	PURPOSE:    Create a mapping for a range of pages from a CPU virtual
+                adddress to a specified device virtual address.
+	                	
+	PARAMETERS: In:  pMMUHeap - the mmu.
+                In:  MapBaseDevVAddr - A page aligned device virtual address
+                                       to start mapping from.
+                In:  uByteSize - A page aligned mapping length in bytes.
+                In:  CpuVAddr - A page aligned CPU virtual address.
+                In:  hOSMemHandle - An alternative OS specific memory handle
+                                    for mapping RAM without a CPU virtual
+                                    address
+                Out: pDevVAddr - deprecated
+                In: hUniqueTag - A unique ID for use as a tag identifier
+                In: ui32MemFlags - page table flags.
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadow (MMU_HEAP          * pMMUHeap,
+               IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+               IMG_SIZE_T          uByteSize,
+               IMG_CPU_VIRTADDR    CpuVAddr,
+               IMG_HANDLE          hOSMemHandle,
+               IMG_DEV_VIRTADDR  * pDevVAddr,
+               IMG_UINT32          ui32MemFlags,
+               IMG_HANDLE          hUniqueTag);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_MapShadowSparse
+
+	PURPOSE:    Create a mapping for a range of pages from a CPU virtual
+                adddress to a specified device virtual address.
+	                	
+	PARAMETERS: In:  pMMUHeap - the mmu.
+                In:  MapBaseDevVAddr - A page aligned device virtual address
+                                       to start mapping from.
+				In:  ui32ChunkSize - Size of the chunk (must be page multiple)
+				In:  ui32NumVirtChunks - Number of virtual chunks
+				In:  ui32NumPhysChunks - Number of physical chunks
+				In:  pabMapChunk - Mapping array
+                In:  CpuVAddr - A page aligned CPU virtual address.
+                In:  hOSMemHandle - An alternative OS specific memory handle
+                                    for mapping RAM without a CPU virtual
+                                    address
+                Out: pDevVAddr - deprecated
+                In: hUniqueTag - A unique ID for use as a tag identifier
+                In: ui32MemFlags - page table flags.
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadowSparse (MMU_HEAP          * pMMUHeap,
+					 IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+					 IMG_UINT32          ui32ChunkSize,
+					 IMG_UINT32          ui32NumVirtChunks,
+					 IMG_UINT32          ui32NumPhysChunks,
+					 IMG_BOOL          * pabMapChunk,
+					 IMG_CPU_VIRTADDR    CpuVAddr,
+					 IMG_HANDLE          hOSMemHandle,
+					 IMG_DEV_VIRTADDR  * pDevVAddr,
+					 IMG_UINT32          ui32MemFlags,
+					 IMG_HANDLE          hUniqueTag);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_UnmapPages
+
+	PURPOSE:    unmaps pages and invalidates virtual address.
+	                	
+	PARAMETERS:	In:  psMMUHeap - the mmu.
+	            In:  sDevVAddr - the device virtual address.
+	            In:  ui32PageCount - page count.
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+             IMG_DEV_VIRTADDR sDevVAddr,
+             IMG_UINT32 ui32PageCount,
+             IMG_HANDLE hUniqueTag);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_MapScatter
+
+	PURPOSE:    Create a mapping for a list of pages to a specified device 
+				virtual address.
+	                	
+	PARAMETERS:	In:  pMMUHeap - the mmu.
+	            In:  DevVAddr - the device virtual address.
+	            In:  psSysAddr - the list of physical addresses of the pages to
+	                 map.
+	RETURNS:	None
+******************************************************************************/
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+				IMG_DEV_VIRTADDR DevVAddr,
+				IMG_SYS_PHYADDR *psSysAddr,
+				IMG_SIZE_T uSize,
+				IMG_UINT32 ui32MemFlags,
+				IMG_HANDLE hUniqueTag);
+
+
+/*
+******************************************************************************
+    FUNCTION:   MMU_GetPhysPageAddr
+
+    PURPOSE:    extracts physical address from MMU page tables
+
+    PARAMETERS: In:  pMMUHeap - the mmu
+	PARAMETERS: In:  sDevVPageAddr - the virtual address to extract physical 
+					page mapping from
+    RETURNS:    IMG_DEV_PHYADDR
+******************************************************************************/
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+
+
+/*
+******************************************************************************
+    FUNCTION:   MMU_GetPDDevPAddr
+
+    PURPOSE:    returns PD given the MMU context (SGX to MMU API)
+
+    PARAMETERS: In:  pMMUContext - the mmu
+    RETURNS:    IMG_DEV_PHYADDR
+******************************************************************************/
+IMG_DEV_PHYADDR
+MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
+
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+/*
+******************************************************************************
+    FUNCTION:   EnableHostAccess
+
+    PURPOSE:    Enables Host accesses to device memory, by passing the device 
+    			MMU address translation
+
+    PARAMETERS: In: psMMUContext
+    RETURNS:    None
+******************************************************************************/
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext);
+
+
+/*
+******************************************************************************
+    FUNCTION:   DisableHostAccess
+
+    PURPOSE:    Disables Host accesses to device memory, by passing the device 
+    			MMU address translation
+
+    PARAMETERS: In: psMMUContext
+    RETURNS:    None
+******************************************************************************/
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext);
+#endif
+
+/*
+******************************************************************************
+    FUNCTION:   MMU_InvalidateDirectoryCache
+
+    PURPOSE:    Invalidates the page directory cache
+
+    PARAMETERS: In: psDevInfo
+    RETURNS:    None
+******************************************************************************/
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_BIFResetPDAlloc
+
+	PURPOSE:    Allocate a dummy Page Directory which causes all virtual
+				addresses to page fault.
+
+	PARAMETERS: In:  psDevInfo - device info
+	RETURNS:    PVRSRV_OK or error
+******************************************************************************/
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_BIFResetPDFree
+
+	PURPOSE:    Free resources allocated in MMU_BIFResetPDAlloc.
+
+	PARAMETERS: In:  psDevInfo - device info
+	RETURNS:
+******************************************************************************/
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*
+******************************************************************************
+	FUNCTION:   MMU_MapExtSystemCacheRegs
+
+	PURPOSE:    maps external system cache control registers into SGX MMU
+
+	PARAMETERS: In:  psDeviceNode - device node
+	RETURNS:
+******************************************************************************/
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_UnmapExtSystemCacheRegs
+
+	PURPOSE:    unmaps external system cache control registers
+
+	PARAMETERS: In:  psDeviceNode - device node
+	RETURNS:
+******************************************************************************/
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif /* #if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) */
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_IsHeapShared
+	
+	PURPOSE:    Is this heap shared?
+	PARAMETERS: In: pMMU_Heap
+	RETURNS:    true if heap is shared
+******************************************************************************/
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMU_Heap);
+
+#if defined(FIX_HW_BRN_31620)
+/*
+******************************************************************************
+	FUNCTION:   MMU_GetCacheFlushRange
+
+	PURPOSE:    Gets device physical address of the mmu context.
+
+	PARAMETERS: In:  pMMUContext - the mmu context
+	            Out:  pui32RangeMask - Bit mask showing which PD cache
+		          lines have changed
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
+
+/*
+******************************************************************************
+	FUNCTION:   MMU_GetPDPhysAddr
+
+	PURPOSE:    Gets device physical address of the mmu contexts PD.
+
+	PARAMETERS: In:  pMMUContext - the mmu context
+	            Out:  psDevPAddr - Address of PD
+	RETURNS:    None
+******************************************************************************/
+IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
+
+#endif
+
+
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32RegVal);
+
+#if defined(PDUMP)
+/*
+******************************************************************************
+	FUNCTION:   MMU_GetPDumpContextID
+
+	PURPOSE:    translates device mem context to unique pdump identifier
+
+	PARAMETERS: In:  hDevMemContext - device memory per-process context
+	RETURNS:	context identifier used internally in pdump
+******************************************************************************/
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext);
+#endif /* #ifdef PDUMP */
+
+#endif /* #ifndef _MMU_H_ */
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/pb.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/pb.c
new file mode 100644
index 0000000..26e2ded
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/pb.c
@@ -0,0 +1,493 @@
+/*************************************************************************/ /*!
+@Title          Parameter Buffer management functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+
+#if !defined(__linux__) && !defined(__QNXNTO__)
+#pragma message("FIXME: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#endif
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC)
+static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC)
+
+static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL;
+static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL;
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
+
+/* override level pointer indirection */
+/* PRQA S 5102 12 */
+IMG_EXPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					  IMG_HANDLE 				hDevCookie,
+					  IMG_BOOL 				bLockOnFailure,
+					  IMG_UINT32 				ui32TotalPBSize,
+					  IMG_HANDLE 				*phSharedPBDesc,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsSharedPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsHWPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	**ppsHWBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO 	***pppsSharedPBDescSubKernelMemInfos,
+					  IMG_UINT32				*ui32SharedPBDescSubKernelMemInfosCount)
+{
+	PVRSRV_STUB_PBDESC *psStubPBDesc;
+	PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL;
+	PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+	PVRSRV_ERROR eError;
+
+	psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+	psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+	if (psStubPBDesc != IMG_NULL)
+	{
+		IMG_UINT32 i;
+		PRESMAN_ITEM psResItem;
+
+		if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING,
+					"SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+					ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+		}
+
+		if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_MEM_INFO *)
+						* psStubPBDesc->ui32SubKernelMemInfosCount,
+					  (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos,
+					  IMG_NULL,
+					  "Array of Kernel Memory Info") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"));
+
+			eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+			goto ExitNotFound;
+		}
+
+		psResItem = ResManRegisterRes(psPerProc->hResManContext,
+									  RESMAN_TYPE_SHARED_PB_DESC,
+									  psStubPBDesc,
+									  0,
+									  &SGXCleanupSharedPBDescCallback);
+
+		if (psResItem == IMG_NULL)
+		{
+			OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
+					  ppsSharedPBDescSubKernelMemInfos,
+					  0);
+			/*not nulling pointer, out of scope*/
+
+			PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+			eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+			goto ExitNotFound;
+		}
+
+		*ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo;
+		*ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo;
+		*ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo;
+		*ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo;
+
+		*ui32SharedPBDescSubKernelMemInfosCount =
+			psStubPBDesc->ui32SubKernelMemInfosCount;
+
+		*pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos;
+
+		for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++)
+		{
+			ppsSharedPBDescSubKernelMemInfos[i] =
+				psStubPBDesc->ppsSubKernelMemInfos[i];
+		}
+
+		psStubPBDesc->ui32RefCount++;
+		*phSharedPBDesc = (IMG_HANDLE)psResItem;
+		return PVRSRV_OK;
+	}
+
+	eError = PVRSRV_OK;
+	if (bLockOnFailure)
+	{
+		if (psResItemCreateSharedPB == IMG_NULL)
+		{
+			psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext,
+				  RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+				  psPerProc,
+				  0,
+				  &SGXCleanupSharedPBDescCreateLockCallback);
+
+			if (psResItemCreateSharedPB == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+				eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+				goto ExitNotFound;
+			}
+			PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+			psPerProcCreateSharedPB = psPerProc;
+		}
+		else
+		{
+			 eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
+		}
+	}
+ExitNotFound:
+	*phSharedPBDesc = IMG_NULL;
+
+	return eError;
+}
+
+
+static PVRSRV_ERROR
+SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
+{
+	/*PVRSRV_STUB_PBDESC **ppsStubPBDesc;*/
+	IMG_UINT32 i;
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
+
+	psStubPBDescIn->ui32RefCount--;
+	if (psStubPBDescIn->ui32RefCount == 0)
+	{
+		IMG_DEV_VIRTADDR sHWPBDescDevVAddr = psStubPBDescIn->sHWPBDescDevVAddr;
+		List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
+		for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
+		{
+			PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
+								  psStubPBDescIn->ppsSubKernelMemInfos[i]);
+		}
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount,
+				  psStubPBDescIn->ppsSubKernelMemInfos,
+				  0);
+		psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL;
+
+		PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo);
+
+		PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo);
+
+		PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo);
+
+		PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo);
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_STUB_PBDESC),
+				  psStubPBDescIn,
+				  0);
+		/*not nulling pointer, copy on stack*/
+
+		/* signal the microkernel to clear its sTAHWPBDesc and s3DHWPBDesc values in sTA3DCtl */
+		SGXCleanupRequest(psDeviceNode,
+						  &sHWPBDescDevVAddr,
+						  PVRSRV_CLEANUPCMD_PB,
+						  CLEANUP_WITH_POLL);
+	}
+	return PVRSRV_OK;
+	/*return PVRSRV_ERROR_INVALID_PARAMS;*/
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
+{
+	PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	return SGXCleanupSharedPBDescKM(psStubPBDesc);
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
+{
+#ifdef DEBUG
+	PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam;
+	PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+#else
+	PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bDummy);
+
+	psPerProcCreateSharedPB = IMG_NULL;
+	psResItemCreateSharedPB = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc)
+{
+	PVR_ASSERT(hSharedPBDesc != IMG_NULL);
+
+	return ResManFreeResByPtr(hSharedPBDesc, CLEANUP_WITH_POLL);
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					 IMG_HANDLE					hDevCookie,
+					 PVRSRV_KERNEL_MEM_INFO		*psSharedPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psBlockKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWBlockKernelMemInfo,
+					 IMG_UINT32					ui32TotalPBSize,
+					 IMG_HANDLE					*phSharedPBDesc,
+					 PVRSRV_KERNEL_MEM_INFO		**ppsSharedPBDescSubKernelMemInfos,
+					 IMG_UINT32					ui32SharedPBDescSubKernelMemInfosCount,
+					 IMG_DEV_VIRTADDR			sHWPBDescDevVAddr)
+{
+	PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL;
+	PVRSRV_ERROR eRet = PVRSRV_ERROR_INVALID_PERPROC;
+	IMG_UINT32 i;
+	PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+	PRESMAN_ITEM psResItem;
+
+	/*
+	 * The caller must have previously called SGXFindSharedPBDesc with
+	 * bLockOnFailure set, and not managed to find a suitable shared PB.
+	 */
+	if (psPerProcCreateSharedPB != psPerProc)
+	{
+		goto NoAdd;
+	}
+	else
+	{
+		PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL);
+
+		ResManFreeResByPtr(psResItemCreateSharedPB, CLEANUP_WITH_POLL);
+
+		PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL);
+		PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+	}
+
+	psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+	psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+	if (psStubPBDesc != IMG_NULL)
+	{
+		if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+		{
+			PVR_DPF((PVR_DBG_WARNING,
+					"SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+					ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+
+		}
+
+		/*
+		 * We make the caller think the add was successful,
+		 * but return the existing shared PB desc rather than
+		 * a new one.
+		 */
+		psResItem = ResManRegisterRes(psPerProc->hResManContext,
+									  RESMAN_TYPE_SHARED_PB_DESC,
+									  psStubPBDesc,
+									  0,
+									  &SGXCleanupSharedPBDescCallback);
+		if (psResItem == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR,
+				"SGXAddSharedPBDescKM: "
+				"Failed to register existing shared "
+				"PBDesc with the resource manager"));
+			goto NoAddKeepPB;
+		}
+
+		/*
+		 * The caller will unreference the PB desc after
+		 * a successful add, so up the reference count.
+		 */
+		psStubPBDesc->ui32RefCount++;
+
+		*phSharedPBDesc = (IMG_HANDLE)psResItem;
+		eRet = PVRSRV_OK;
+		goto NoAddKeepPB;
+	}
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_STUB_PBDESC),
+				  (IMG_VOID **)&psStubPBDesc,
+				  0,
+				  "Stub Parameter Buffer Description") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
+					"StubPBDesc"));
+		eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto NoAdd;
+	}
+
+
+	psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_KERNEL_MEM_INFO *)
+				  * ui32SharedPBDescSubKernelMemInfosCount,
+				  (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos,
+				  0,
+				  "Array of Kernel Memory Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+				 "Failed to alloc "
+				 "StubPBDesc->ppsSubKernelMemInfos"));
+		eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo)
+	   != PVRSRV_OK)
+	{
+		goto NoAdd;
+	}
+
+	psStubPBDesc->ui32RefCount = 1;
+	psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+	psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+	psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+	psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+	psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo;
+
+	psStubPBDesc->ui32SubKernelMemInfosCount =
+		ui32SharedPBDescSubKernelMemInfosCount;
+	for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+	{
+		psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i];
+		if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i])
+		   != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+					 "Failed to dissociate shared PBDesc "
+					 "from process"));
+			goto NoAdd;
+		}
+	}
+
+	psStubPBDesc->sHWPBDescDevVAddr = sHWPBDescDevVAddr;
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_SHARED_PB_DESC,
+								  psStubPBDesc,
+								  0,
+								  &SGXCleanupSharedPBDescCallback);
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+					 "Failed to register shared PBDesc "
+					 " with the resource manager"));
+		goto NoAdd;
+	}
+	psStubPBDesc->hDevCookie = hDevCookie;
+
+	/* Finally everything was prepared successfully so link the new
+	 * PB in to place. */
+	List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
+									psStubPBDesc);
+
+	*phSharedPBDesc = (IMG_HANDLE)psResItem;
+
+	return PVRSRV_OK;
+
+NoAdd:
+	if(psStubPBDesc)
+	{
+		if(psStubPBDesc->ppsSubKernelMemInfos)
+		{
+			OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+					  sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+					  psStubPBDesc->ppsSubKernelMemInfos,
+					  0);
+			psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+		}
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_STUB_PBDESC),
+				  psStubPBDesc,
+				  0);
+		/*not nulling pointer, out of scope*/
+	}
+
+NoAddKeepPB:
+	for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
+	{
+		PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]);
+	}
+
+	PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
+	PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
+
+	PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
+	PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo);
+
+	return eRet;
+}
+
+/******************************************************************************
+ End of file (pb.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
new file mode 100644
index 0000000..260a265
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgx_bridge_km.h
@@ -0,0 +1,254 @@
+/*************************************************************************/ /*!
+@Title          SGX Bridge Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the SGX Bridge code
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__SGX_BRIDGE_KM_H__)
+#define __SGX_BRIDGE_KM_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgx_bridge.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle,
+						 SGX_CCB_KICK *psCCBKick);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM(IMG_HANDLE hDevMemHeap,
+								  IMG_DEV_VIRTADDR sDevVAddr,
+								  IMG_DEV_PHYADDR *pDevPAddr,
+								  IMG_CPU_PHYADDR *pCpuPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SGXGetMMUPDAddrKM(IMG_HANDLE		hDevCookie,
+											IMG_HANDLE		hDevMemContext,
+											IMG_DEV_PHYADDR	*psPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE				hDevCookie,
+								SGX_CLIENT_INFO*	psClientInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							  SGX_MISC_INFO			*psMiscInfo,
+							  PVRSRV_DEVICE_NODE 	*psDeviceNode,
+							  IMG_HANDLE 			 hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE					hDevHandle,
+							   IMG_UINT32					ui32ArraySize,
+							   PVRSRV_SGX_HWPERF_CB_ENTRY	*psHWPerfCBData,
+							   IMG_UINT32					*pui32DataCount,
+							   IMG_UINT32					*pui32ClockSpeed,
+							   IMG_UINT32					*pui32HostTimeStamp);
+
+IMG_IMPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO		*psDevInfo,
+									   PVRSRV_KERNEL_SYNC_INFO	*psSyncInfo,
+									   IMG_BOOL bWaitForComplete);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
+									SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+							   IMG_HANDLE hDevHandle,
+							   SGX_BRIDGE_INIT_INFO *psInitInfo);
+
+/*!
+ * *****************************************************************************
+ * @brief Looks for a parameter buffer description that corresponds to
+ *        a buffer of size ui32TotalPBSize, optionally taking the lock
+ *        needed for SharedPBCreation on failure.
+ *
+ *        Note if a PB Desc is found then its internal reference counter
+ *        is automatically incremented. It is your responsability to call
+ *        SGXUnrefSharedPBDesc to decrement this reference and free associated
+ *        resources when you are done.
+ *
+ * 	  If bLockOnFailure is set, and a suitable shared PB isn't found,
+ * 	  an internal flag is set, allowing this process to create a
+ * 	  shared PB.  Any other process calling this function with
+ * 	  bLockOnFailure set, will receive the return code
+ * 	  PVRSRV_ERROR_PROCESSING_BLOCKED, indicating that it needs
+ * 	  to retry the function call.  The internal flag is cleared
+ * 	  when this process creates a shared PB.
+ *
+ *	  Note: You are responsible for freeing the list returned in
+ *	  pppsSharedPBDescSubKernelMemInfos
+ *	  via OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ *					sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ *					  * ui32SharedPBDescSubKernelMemInfosCount,
+ *					ppsSharedPBDescSubKernelMemInfos,
+ *					NULL);
+ *
+ * @param[in] psPerProc
+ * @param[in] hDevCookie
+ * @param[in] bLockOnError
+ * @param[in] ui32TotalPBSize
+ * @param[in] phSharedPBDesc
+ * @param[out] ppsSharedPBDescKernelMemInfo
+ * @param[out] ppsHWPBDescKernelMemInfo
+ * @param[out] pppsSharedPBDescSubKernelMemInfos  A list of integral sub meminfos.
+ * @param[out] ui32SharedPBDescSubKernelMemInfosCount
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
+/* disable QAC pointer level check for over 2 */
+/* PRQA S 5102++ */
+IMG_IMPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					  IMG_HANDLE				hDevCookie,
+					  IMG_BOOL				bLockOnFailure,
+					  IMG_UINT32				ui32TotalPBSize,
+					  IMG_HANDLE				*phSharedPBDesc,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsSharedPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsHWPBDescKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	**ppsHWBlockKernelMemInfo,
+					  PVRSRV_KERNEL_MEM_INFO	***pppsSharedPBDescSubKernelMemInfos,
+					  IMG_UINT32				*ui32SharedPBDescSubKernelMemInfosCount);
+
+/*!
+ * *****************************************************************************
+ * @brief Decrements the reference counter and frees all userspace resources
+ *        associated with a SharedPBDesc.
+ *
+ * @param hSharedPBDesc
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+
+/*!
+ * *****************************************************************************
+ * @brief Links a new SharedPBDesc into a kernel managed list that can
+ *        then be queried by other clients.
+ *
+ *        As a side affect this function also dissociates the SharedPBDesc
+ *        from the calling process so that the memory won't be freed if the
+ *        process dies/exits. (The kernel assumes responsability over the
+ *        memory at the same time)
+ *
+ *        As well as the psSharedPBDescKernelMemInfo you must also pass
+ *        a complete list of other meminfos that are integral to the
+ *        shared PB description. (Although the kernel doesn't have direct
+ *        access to the shared PB desc it still needs to be able to
+ *        clean up all the associated resources when it is no longer
+ *        in use.)
+ *
+ *        If the dissociation fails then all the memory associated with
+ *	  the psSharedPBDescKernelMemInfo and all entries in psKernelMemInfos
+ *	  will be freed by kernel services! Because of this, you are
+ *	  responsible for freeing the corresponding client meminfos _before_
+ *	  calling SGXAddSharedPBDescKM.
+ *
+ * 	  This function will return an error unless a succesful call to
+ * 	  SGXFindSharedPBDesc, with bLockOnFailure set, has been made.
+ *
+ * @param psPerProc
+ * @param hDevCookie
+ * @param psSharedPBDescKernelMemInfo
+ * @param psHWPBDescKernelMemInfo
+ * @param psBlockKernelMemInfo
+ * @param ui32TotalPBSize  The size of the associated parameter buffer
+ * @param ppsSharedPBDescSubKernelMemInfos  A list of other meminfos integral to
+ * 										    the shared PB description.
+ * @param ui32SharedPBDescSubKernelMemInfosCount  The number of entires in
+ * 												  psKernelMemInfos
+ * @param sHWPBDescDevVAddr The device virtual address of the HWPBDesc
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA	*psPerProc,
+					 IMG_HANDLE 				hDevCookie,
+					 PVRSRV_KERNEL_MEM_INFO		*psSharedPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWPBDescKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psBlockKernelMemInfo,
+					 PVRSRV_KERNEL_MEM_INFO		*psHWBlockKernelMemInfo,
+					 IMG_UINT32					ui32TotalPBSize,
+					 IMG_HANDLE					*phSharedPBDesc,
+					 PVRSRV_KERNEL_MEM_INFO		**psSharedPBDescSubKernelMemInfos,
+					 IMG_UINT32					ui32SharedPBDescSubKernelMemInfosCount,
+					 IMG_DEV_VIRTADDR			sHWPBDescDevVAddr);
+
+
+/*!
+ * *****************************************************************************
+ * @brief Gets device information that is not intended to be passed
+		  on beyond the srvclient libs.
+ *
+ * @param[in] hDevCookie
+ * @param[out] psSGXInternalDevInfo
+ *
+ * @return
+ ********************************************************************************/
+IMG_IMPORT PVRSRV_ERROR
+SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+						SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __SGX_BRIDGE_KM_H__ */
+
+/******************************************************************************
+ End of file (sgx_bridge_km.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxconfig.h b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxconfig.h
new file mode 100644
index 0000000..009a8d7
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxconfig.h
@@ -0,0 +1,645 @@
+/*************************************************************************/ /*!
+@Title          device configuration
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __SGXCONFIG_H__
+#define __SGXCONFIG_H__
+
+#include "sgxdefs.h"
+
+#define DEV_DEVICE_TYPE			PVRSRV_DEVICE_TYPE_SGX
+#define DEV_DEVICE_CLASS		PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION		1
+#define DEV_MINOR_VERSION		0
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+#define SGX_KERNEL_DATA_HEAP_OFFSET		0x00001000
+#else
+#define SGX_KERNEL_DATA_HEAP_OFFSET		0x00000000
+#endif
+
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+
+#if defined (SGX_FEATURE_ADDRESS_SPACE_EXTENSION)
+/*
+ * Constraints: (Additional to above ones)
+ *	-GENERAL, PDS, USE_CODE, KERNEL_DATA heaps should be within [0-256MB] range only.
+ *	-(3DPARAMETERS_HEAP_BASE+TADATA_HEAP) <= 256MB, within same 256MB range.
+ *	
+ * BIF_REQ_BASE Setting:
+ *	-PDS_REQ_BASE = USCE_REQ_BASE = VDM_REQ_BASE = 0x00000000 
+ * 3D Task:
+ *	-ISPP_REQ_BASE = ISPZ_REQ_BASE = 3D_REQ_BASE = 3DPARAMETERS_HEAP_BASE
+ * TA Task:
+ *	-TA_COMMON_REQ_BASE = TA_REQ_BASE = 3DPARAMETERS_HEAP_BASE
+ * TQ Task:
+ *	-3D_REQ_BASE = ISPP_REQ_BASE = ISPZ_REQ_BASE = ISP stream CCB base
+ */
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#define SGX_GENERAL_MAPPING_HEAP_BASE		 0x00001000
+	#define SGX_GENERAL_MAPPING_HEAP_SIZE		(0x01400000-0x00001000-0x00001000)
+
+	#define SGX_GENERAL_HEAP_BASE				 0x01400000
+	#define SGX_GENERAL_HEAP_SIZE				(0x07000000-0x00001000)
+
+#else
+	#define SGX_GENERAL_HEAP_BASE				 0x00001000
+	#define SGX_GENERAL_HEAP_SIZE				(0x08400000-0x00001000-0x00001000)
+#endif
+
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE		 0x08400000
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE		(0x02000000-0x00001000)
+
+	#define SGX_KERNEL_CODE_HEAP_BASE			 0x0A400000
+	#define SGX_KERNEL_CODE_HEAP_SIZE			(0x00080000-0x00001000)
+
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE	 0x0A800000
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE	(0x01C00000-0x00001000)
+
+	#define SGX_PIXELSHADER_HEAP_BASE			 0x0C400000
+	#define SGX_PIXELSHADER_HEAP_SIZE			(0x00800000-0x00001000)
+
+	#define SGX_VERTEXSHADER_HEAP_BASE			 0x0CC00000
+	#define SGX_VERTEXSHADER_HEAP_SIZE			(0x00400000-0x00001000)
+
+	#define SGX_KERNEL_DATA_HEAP_BASE			(0x0D000000+SGX_KERNEL_DATA_HEAP_OFFSET)
+	#define SGX_KERNEL_DATA_HEAP_SIZE			(0x02F00000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
+
+	/* ==== Heaps 256MB onwards ==== */
+
+	#define SGX_3DPARAMETERS_HEAP_SIZE			0x04000000
+
+	/* By default we split the PB 50/50 */
+#if !defined(HYBRID_SHARED_PB_SIZE)
+	#define HYBRID_SHARED_PB_SIZE				(SGX_3DPARAMETERS_HEAP_SIZE >> 1)
+#endif
+#if defined(SUPPORT_HYBRID_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			(HYBRID_SHARED_PB_SIZE)
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(HYBRID_SHARED_PB_SIZE-0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - SGX_SHARED_3DPARAMETERS_SIZE - 0x00001000)
+#else
+#if defined(SUPPORT_PERCONTEXT_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			0
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		0
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+#endif
+#if defined(SUPPORT_SHARED_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			SGX_3DPARAMETERS_HEAP_SIZE
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		0
+#endif
+#endif
+
+	#define SGX_SHARED_3DPARAMETERS_HEAP_BASE		 0x10000000
+
+	/* Size is defined above */
+
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE		 (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
+	/* Size is defined above */
+
+	#define SGX_TADATA_HEAP_BASE				 0x14000000
+	#define SGX_TADATA_HEAP_SIZE				(0x04000000-0x00001000)
+
+	#define SGX_SYNCINFO_HEAP_BASE				 0x18000000
+	#define SGX_SYNCINFO_HEAP_SIZE				(0x01000000-0x00001000)
+
+    #define SGX_TEXTURE_HEAP_BASE                0x19000000
+    #define SGX_TEXTURE_HEAP_SIZE               (0xE6000000-0x00001000)
+
+#else /* defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION) */ 
+#if defined(FIX_HW_BRN_31620)
+	#if defined(SGX_FEATURE_2D_HARDWARE)
+	#define SGX_2D_HEAP_BASE					 0x04000000
+	#define SGX_2D_HEAP_SIZE					(0x08000000-0x04000000-0x00001000)
+	#endif
+
+	#define SGX_GENERAL_HEAP_BASE				 0x08000000
+	#define SGX_GENERAL_HEAP_SIZE				(0xB8000000-0x00001000)
+
+	/*
+	 * For hybrid PB we have to split virtual PB range between the shared
+	 * PB and percontext PB due to the fact we only have one heap config
+	 * per device.
+	 * If hybrid PB is enabled we split the space according to HYBRID_SHARED_PB_SIZE.
+	 * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+	 * remainder is the size of the percontext PB.
+	 * If hybrid PB is not enabled then we still create both heaps (helps keep
+	 * the code clean) and define the size of the unused one to 0
+	 */
+
+	#define SGX_3DPARAMETERS_HEAP_SIZE			0x10000000
+
+	/* By default we split the PB 50/50 */
+#if !defined(HYBRID_SHARED_PB_SIZE)
+	#define HYBRID_SHARED_PB_SIZE				(SGX_3DPARAMETERS_HEAP_SIZE >> 1)
+#endif
+#if defined(SUPPORT_HYBRID_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			(HYBRID_SHARED_PB_SIZE)
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(HYBRID_SHARED_PB_SIZE-0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - SGX_SHARED_3DPARAMETERS_SIZE - 0x00001000)
+#else
+#if defined(SUPPORT_PERCONTEXT_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			0
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		0
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+#endif
+#if defined(SUPPORT_SHARED_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			SGX_3DPARAMETERS_HEAP_SIZE
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		0
+#endif
+#endif
+
+	#define SGX_SHARED_3DPARAMETERS_HEAP_BASE		 0xC0000000
+	/* Size is defined above */
+
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE		 (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
+	/* Size is defined above */
+
+	#define SGX_TADATA_HEAP_BASE				 0xD0000000
+	#define SGX_TADATA_HEAP_SIZE				(0x0D000000-0x00001000)
+
+	#define SGX_SYNCINFO_HEAP_BASE				 0xE0000000
+	#define SGX_SYNCINFO_HEAP_SIZE				(0x01000000-0x00001000)
+
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE		 0xE4000000
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE		(0x02000000-0x00001000)
+
+	#define SGX_KERNEL_CODE_HEAP_BASE			 0xE8000000
+	#define SGX_KERNEL_CODE_HEAP_SIZE			(0x00080000-0x00001000)
+
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE	 0xEC000000
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE	(0x01C00000-0x00001000)
+
+	#define SGX_KERNEL_DATA_HEAP_BASE		 	(0xF0000000+SGX_KERNEL_DATA_HEAP_OFFSET)
+	#define SGX_KERNEL_DATA_HEAP_SIZE			(0x03000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
+
+	/* Actual Pixel and Vertex shared heaps sizes may be reduced by
+	 * override - see SGX_USE_CODE_SEGMENT_RANGE_BITS.*/
+	#define SGX_PIXELSHADER_HEAP_BASE			 0xF4000000
+	#define SGX_PIXELSHADER_HEAP_SIZE			(0x05000000-0x00001000)
+	
+	#define SGX_VERTEXSHADER_HEAP_BASE			 0xFC000000
+	#define SGX_VERTEXSHADER_HEAP_SIZE			(0x02000000-0x00001000)
+#else /* FIX_HW_BRN_31620 */
+	#if defined(SGX_FEATURE_2D_HARDWARE)
+	#define SGX_2D_HEAP_BASE					 0x00100000
+	#define SGX_2D_HEAP_SIZE					(0x08000000-0x00100000-0x00001000)
+	#endif
+
+	#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#define SGX_GENERAL_MAPPING_HEAP_BASE		 0x08000000
+	#define SGX_GENERAL_MAPPING_HEAP_SIZE		(0x08000000-0x00001000)
+	#endif
+
+	#if !defined(SUPPORT_MEMORY_TILING)
+		#define SGX_GENERAL_HEAP_BASE				 0x10000000
+		#define SGX_GENERAL_HEAP_SIZE				(0xC2000000-0x00001000)
+	#else
+		#include <sgx_msvdx_defs.h>
+		/* Create heaps with memory tiling enabled.
+	 	 * SGX HW limit is 10 heaps.
+	 	 */
+	 	/* Tiled heap space is taken from general heap */
+	 	#define SGX_GENERAL_HEAP_BASE				 0x10000000
+		#define SGX_GENERAL_HEAP_SIZE				(0xB5000000-0x00001000)
+
+		#define SGX_VPB_TILED_HEAP_STRIDE			TILING_TILE_STRIDE_2K
+		#define SGX_VPB_TILED_HEAP_BASE		 0xC5000000
+		#define SGX_VPB_TILED_HEAP_SIZE	(0x0D000000-0x00001000)
+
+		/* Check tiled heap base alignment */
+		#if((SGX_VPB_TILED_HEAP_BASE & SGX_BIF_TILING_ADDR_INV_MASK) != 0)
+		#error "sgxconfig.h: SGX_VPB_TILED_HEAP has insufficient alignment"
+		#endif
+
+	#endif /* SUPPORT_MEMORY_TILING */
+
+	/*
+	 * For hybrid PB we have to split virtual PB range between the shared
+	 * PB and percontext PB due to the fact we only have one heap config
+	 * per device.
+	 * If hybrid PB is enabled we split the space according to HYBRID_SHARED_PB_SIZE.
+	 * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+	 * remainder is the size of the percontext PB.
+	 * If hybrid PB is not enabled then we still create both heaps (helps keep
+	 * the code clean) and define the size of the unused one to 0
+	 */
+
+	#define SGX_3DPARAMETERS_HEAP_SIZE			0x10000000
+
+	/* By default we split the PB 50/50 */
+#if !defined(HYBRID_SHARED_PB_SIZE)
+	#define HYBRID_SHARED_PB_SIZE				(SGX_3DPARAMETERS_HEAP_SIZE >> 1)
+#endif
+#if defined(SUPPORT_HYBRID_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			(HYBRID_SHARED_PB_SIZE)
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(HYBRID_SHARED_PB_SIZE-0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - SGX_SHARED_3DPARAMETERS_SIZE - 0x00001000)
+#else
+#if defined(SUPPORT_PERCONTEXT_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			0
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		0
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+#endif
+#if defined(SUPPORT_SHARED_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			SGX_3DPARAMETERS_HEAP_SIZE
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		0
+#endif
+#endif
+
+	#define SGX_SHARED_3DPARAMETERS_HEAP_BASE		 0xD2000000
+	/* Size is defined above */
+
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE		 (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
+	/* Size is defined above */
+
+	#define SGX_TADATA_HEAP_BASE				 0xE2000000
+	#define SGX_TADATA_HEAP_SIZE				(0x0D000000-0x00001000)
+
+	#define SGX_SYNCINFO_HEAP_BASE				 0xEF000000
+	#define SGX_SYNCINFO_HEAP_SIZE				(0x01000000-0x00001000)
+
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE		 0xF0000000
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE		(0x02000000-0x00001000)
+
+	#define SGX_KERNEL_CODE_HEAP_BASE			 0xF2000000
+	#define SGX_KERNEL_CODE_HEAP_SIZE			(0x00080000-0x00001000)
+
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE	 0xF2400000
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE	(0x01C00000-0x00001000)
+
+	#define SGX_KERNEL_DATA_HEAP_BASE		 	(0xF4000000+SGX_KERNEL_DATA_HEAP_OFFSET)
+	#define SGX_KERNEL_DATA_HEAP_SIZE			(0x05000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
+
+	/* Actual Pixel and Vertex shared heaps sizes may be reduced by
+	 * override - see SGX_USE_CODE_SEGMENT_RANGE_BITS.*/
+	#define SGX_PIXELSHADER_HEAP_BASE			 0xF9000000
+	#define SGX_PIXELSHADER_HEAP_SIZE			(0x05000000-0x00001000)
+	
+	#define SGX_VERTEXSHADER_HEAP_BASE			 0xFE000000
+	#define SGX_VERTEXSHADER_HEAP_SIZE			(0x02000000-0x00001000)
+#endif /* FIX_HW_BRN_31620 */
+	/* signal we've identified the core by the build */
+#endif /* defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION) */
+	#define SGX_CORE_IDENTIFIED
+#endif /* SGX_FEATURE_ADDRESS_SPACE_SIZE == 32 */
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#define SGX_GENERAL_MAPPING_HEAP_BASE		 0x00001000
+	#define SGX_GENERAL_MAPPING_HEAP_SIZE		(0x01800000-0x00001000-0x00001000)
+
+	#define SGX_GENERAL_HEAP_BASE				 0x01800000
+	#define SGX_GENERAL_HEAP_SIZE				(0x07000000-0x00001000)
+
+#else
+	#define SGX_GENERAL_HEAP_BASE				 0x00001000
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+	#define SGX_GENERAL_HEAP_SIZE				(0x0B800000-0x00001000-0x00001000)
+#else
+	#define SGX_GENERAL_HEAP_SIZE				(0x08800000-0x00001000-0x00001000)
+#endif
+#endif
+
+	/*
+	 * For hybrid PB we have to split virtual PB range between the shared
+	 * PB and percontext PB due to the fact we only have one heap config
+	 * per device.
+ 	 * If hybrid PB is enabled we split the space according to HYBRID_SHARED_PB_SIZE.
+	 * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+	 * remainder is the size of the percontext PB.
+	 * If hybrid PB is not enabled then we still create both heaps (helps keep
+	 * the code clean) and define the size of the unused one to 0
+	 */
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+	#define SGX_3DPARAMETERS_HEAP_SIZE			0x01000000
+#else
+	#define SGX_3DPARAMETERS_HEAP_SIZE			0x04000000
+#endif
+
+	/* By default we split the PB 50/50 */
+#if !defined(HYBRID_SHARED_PB_SIZE)
+	#define HYBRID_SHARED_PB_SIZE				(SGX_3DPARAMETERS_HEAP_SIZE >> 1)
+#endif
+#if defined(SUPPORT_HYBRID_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			(HYBRID_SHARED_PB_SIZE)
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(HYBRID_SHARED_PB_SIZE-0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - SGX_SHARED_3DPARAMETERS_SIZE - 0x00001000)
+#else
+#if defined(SUPPORT_PERCONTEXT_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			0
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		0
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+#endif
+#if defined(SUPPORT_SHARED_PB)
+	#define SGX_SHARED_3DPARAMETERS_SIZE			SGX_3DPARAMETERS_HEAP_SIZE
+	#define SGX_SHARED_3DPARAMETERS_HEAP_SIZE		(SGX_3DPARAMETERS_HEAP_SIZE - 0x00001000)
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE		0
+#endif
+#endif
+
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+	#define SGX_SHARED_3DPARAMETERS_HEAP_BASE		 0x0B800000
+#else
+	#define SGX_SHARED_3DPARAMETERS_HEAP_BASE		 0x08800000
+#endif
+
+	/* Size is defined above */
+
+	#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE		 (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
+	/* Size is defined above */
+
+	#define SGX_TADATA_HEAP_BASE				 0x0C800000
+	#define SGX_TADATA_HEAP_SIZE				(0x01000000-0x00001000)
+
+	#define SGX_SYNCINFO_HEAP_BASE				 0x0D800000
+	#define SGX_SYNCINFO_HEAP_SIZE				(0x00400000-0x00001000)
+
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE		 0x0DC00000
+	#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE		(0x00800000-0x00001000)
+
+	#define SGX_KERNEL_CODE_HEAP_BASE			 0x0E400000
+	#define SGX_KERNEL_CODE_HEAP_SIZE			(0x00080000-0x00001000)
+
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE	 0x0E800000
+	#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE	(0x00800000-0x00001000)
+
+	#define SGX_KERNEL_DATA_HEAP_BASE			(0x0F000000+SGX_KERNEL_DATA_HEAP_OFFSET)
+	#define SGX_KERNEL_DATA_HEAP_SIZE			(0x00400000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
+
+	#define SGX_PIXELSHADER_HEAP_BASE			 0x0F400000
+	#define SGX_PIXELSHADER_HEAP_SIZE			(0x00500000-0x00001000)
+
+	#define SGX_VERTEXSHADER_HEAP_BASE			 0x0FC00000
+	#define SGX_VERTEXSHADER_HEAP_SIZE			(0x00200000-0x00001000)
+
+	/* signal we've identified the core by the build */
+	#define SGX_CORE_IDENTIFIED
+
+#endif /* SGX_FEATURE_ADDRESS_SPACE_SIZE == 28 */
+
+#if !defined(SGX_CORE_IDENTIFIED)
+	#error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#if !defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION)
+/*********************************************************************************
+ *
+ * SGX_PDSPIXEL_CODEDATA_HEAP_BASE + 64MB range must include PDSVERTEX_CODEDATA and KERNEL_CODE heaps
+ *
+ ********************************************************************************/
+#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE)
+	#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) >  0x4000000)
+	 	#error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+	#endif
+	
+	#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) >  0x4000000)
+	 	#error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+	#endif
+#endif	
+
+/*********************************************************************************
+ *
+ * The General Mapping heap must be within the 2D requestor range of the 2D heap base
+ *
+ ********************************************************************************/
+#if defined(SGX_FEATURE_2D_HARDWARE) && defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE - SGX_2D_HEAP_BASE) >= EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK)
+		#error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP inaccessable by 2D requestor"
+	#endif
+#endif
+
+/*********************************************************************************
+ *
+ * The kernel code heap base must be aligned to a USSE code page
+ *
+ ********************************************************************************/
+#if defined (EURASIA_USE_CODE_PAGE_SIZE)
+	#if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0)
+		#error "sgxconfig.h: ERROR: Kernel code heap base misalignment"
+	#endif
+#endif
+
+/*********************************************************************************
+ *
+ * Heap overlap check
+ *
+ ********************************************************************************/
+#if defined(SGX_FEATURE_2D_HARDWARE)
+	#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+		#if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
+			#error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
+		#endif
+	#else
+		#if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+			#error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_HEAP_BASE"
+		#endif
+	#endif
+#endif
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+		#error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP overlaps SGX_GENERAL_HEAP"
+	#endif
+#endif
+
+#if defined(SUPPORT_HYBRID_PB)
+	#if ((HYBRID_SHARED_PB_SIZE + 0x000001000) > SGX_3DPARAMETERS_HEAP_SIZE)
+		#error "sgxconfig.h: ERROR: HYBRID_SHARED_PB_SIZE too large"
+	#endif
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+	#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_VPB_TILED_HEAP_BASE)
+		#error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_VPB_TILED_HEAP"
+	#endif
+	#if ((SGX_VPB_TILED_HEAP_BASE + SGX_VPB_TILED_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+		#error "sgxconfig.h: ERROR: SGX_VPB_TILED_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+	#endif
+#else
+	#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+		#error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+	#endif
+#endif
+
+#if (((SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE + SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE) && (SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE > 0))
+	#error "sgxconfig.h: ERROR: SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE overlaps SGX_TADATA_HEAP"
+#endif
+
+#if ((SGX_TADATA_HEAP_BASE + SGX_TADATA_HEAP_SIZE) >= SGX_SYNCINFO_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_TADATA_HEAP overlaps SGX_SYNCINFO_HEAP"
+#endif
+
+#if ((SGX_SYNCINFO_HEAP_BASE + SGX_SYNCINFO_HEAP_SIZE) >= SGX_PDSPIXEL_CODEDATA_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_SYNCINFO_HEAP overlaps SGX_PDSPIXEL_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSPIXEL_CODEDATA_HEAP_BASE + SGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_CODE_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_PDSPIXEL_CODEDATA_HEAP overlaps SGX_KERNEL_CODE_HEAP"
+#endif
+
+#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE) >= SGX_PDSVERTEX_CODEDATA_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP overlaps SGX_PDSVERTEX_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_DATA_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP overlaps SGX_KERNEL_DATA_HEAP"
+#endif
+
+#if ((SGX_KERNEL_DATA_HEAP_BASE + SGX_KERNEL_DATA_HEAP_SIZE) >= SGX_PIXELSHADER_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_KERNEL_DATA_HEAP overlaps SGX_PIXELSHADER_HEAP"
+#endif
+
+#if ((SGX_PIXELSHADER_HEAP_BASE + SGX_PIXELSHADER_HEAP_SIZE) >= SGX_VERTEXSHADER_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_PIXELSHADER_HEAP overlaps SGX_VERTEXSHADER_HEAP"
+#endif
+
+#if ((SGX_VERTEXSHADER_HEAP_BASE + SGX_VERTEXSHADER_HEAP_SIZE) < SGX_VERTEXSHADER_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size cause wraparound"
+#endif
+#else	/* !defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION) */
+
+/*********************************************************************************
+ *
+ * SGX_PDSPIXEL_CODEDATA_HEAP_BASE + 64MB range must include PDSVERTEX_CODEDATA and KERNEL_CODE heaps
+ *
+ ********************************************************************************/
+#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE)
+	#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) >  0x4000000)
+	 	#error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+	#endif
+	
+	#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) >  0x4000000)
+	 	#error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+	#endif
+#endif	
+
+/*********************************************************************************
+ *
+ * The kernel code heap base must be aligned to a USSE code page
+ *
+ ********************************************************************************/
+#if defined (EURASIA_USE_CODE_PAGE_SIZE)
+	#if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0)
+		#error "sgxconfig.h: ERROR: Kernel code heap base misalignment"
+	#endif
+#endif
+
+/*********************************************************************************
+ *
+ * Heap overlap check
+ *
+ ********************************************************************************/
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	#if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+		#error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP overlaps SGX_GENERAL_HEAP"
+	#endif
+#endif
+
+#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_PDSPIXEL_CODEDATA_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_PDSPIXEL_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSPIXEL_CODEDATA_HEAP_BASE + SGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_CODE_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_PDSPIXEL_CODEDATA_HEAP overlaps SGX_KERNEL_CODE_HEAP"
+#endif
+
+#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE) >= SGX_PDSVERTEX_CODEDATA_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP overlaps SGX_PDSVERTEX_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= SGX_PIXELSHADER_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP overlaps SGX_KERNEL_DATA_HEAP"
+#endif
+
+#if ((SGX_PIXELSHADER_HEAP_BASE + SGX_PIXELSHADER_HEAP_SIZE) >= SGX_VERTEXSHADER_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_PIXELSHADER_HEAP overlaps SGX_VERTEXSHADER_HEAP"
+#endif
+
+#if ((SGX_VERTEXSHADER_HEAP_BASE + SGX_VERTEXSHADER_HEAP_SIZE) >= SGX_KERNEL_DATA_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size overlaps SGX_KERNEL_DATA_HEAP"
+#endif
+
+/* check if last heap in 0-256MB spill out of 256MB */
+#if ((SGX_KERNEL_DATA_HEAP_BASE + SGX_KERNEL_DATA_HEAP_SIZE) > 0x0FFFFFFF)
+	#error "sgxconfig.h: ERROR: SGX_KERNEL_DATA_HEAP spill out of 256MB"
+#endif
+
+
+/* check for heaps out 0f 0-256MB range */
+
+
+#if ((SGX_SHARED_3DPARAMETERS_HEAP_BASE < 0x0FFFFFFF))
+	#error "sgxconfig.h: ERROR: put SGX_SHARED_3DPARAMETERS_HEAP out side of 0-256MB"
+#endif
+
+#if defined(SUPPORT_HYBRID_PB)
+	#if ((HYBRID_SHARED_PB_SIZE + 0x000001000) > SGX_3DPARAMETERS_HEAP_SIZE)
+		#error "sgxconfig.h: ERROR: HYBRID_SHARED_PB_SIZE too large"
+	#endif
+#endif
+
+#if (((SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE + SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE) && (SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE > 0))
+	#error "sgxconfig.h: ERROR: SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE overlaps SGX_TADATA_HEAP"
+#endif
+
+#if ((SGX_TADATA_HEAP_BASE + SGX_TADATA_HEAP_SIZE) >= SGX_SYNCINFO_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_TADATA_HEAP overlaps SGX_SYNCINFO_HEAP"
+#endif
+
+#if ((SGX_SYNCINFO_HEAP_BASE + SGX_SYNCINFO_HEAP_SIZE) >= SGX_TEXTURE_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_SYNCINFO_HEAP overlaps SGX_TEXTURE_HEAP_BASE"
+#endif
+
+#if ((SGX_TEXTURE_HEAP_BASE + SGX_TEXTURE_HEAP_SIZE) < SGX_TEXTURE_HEAP_BASE)
+	#error "sgxconfig.h: ERROR: SGX_TEXTURE_HEAP size cause wraparound"
+#endif
+
+#endif /* !defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION) */
+#endif /* __SGXCONFIG_H__ */
+
+/*****************************************************************************
+ End of file (sgxconfig.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxinfokm.h b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
new file mode 100644
index 0000000..eb1b21d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxinfokm.h
@@ -0,0 +1,631 @@
+/*************************************************************************/ /*!
+@Title          SGX kernel services structues/functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Structures and inline functions for KM services component
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __SGXINFOKM_H__
+#define __SGXINFOKM_H__
+
+#include "sgxdefs.h"
+#include "device.h"
+#include "power.h"
+#include "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/****************************************************************************/
+/* kernel only defines: 													*/
+/****************************************************************************/
+/* SGXDeviceMap Flag defines */
+#define		SGX_HOSTPORT_PRESENT			0x00000001UL
+
+
+/*
+	SGX PDUMP register bank name (prefix)
+*/
+#define SGX_PDUMPREG_NAME		"SGXREG"
+
+/****************************************************************************/
+/* kernel only structures: 													*/
+/****************************************************************************/
+
+/*Forward declaration*/
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+typedef struct _PVRSRV_SYSTRACE_JOB_
+{
+	IMG_UINT32 ui32JobID;
+	IMG_UINT32 ui32FrameNum;
+	IMG_UINT32 ui32RTData;
+	
+} PVRSRV_SYSTRACE_JOB;
+
+typedef struct _PVRSRV_SYSTRACE_CONTEXT_
+{
+	IMG_UINT32 ui32PID;
+	IMG_UINT32 ui32CtxID;
+
+	/*Every PID has a circular buffer of jobs*/
+	IMG_UINT32 ui32Start;
+	IMG_UINT32 ui32End;
+	IMG_UINT32 ui32CurrentJobID;
+	PVRSRV_SYSTRACE_JOB asJobs[16];
+	
+} PVRSRV_SYSTRACE_CONTEXT;
+
+typedef struct _PVRSRV_SYSTRACE_TIMECORR_
+{
+	IMG_UINT64 ui64HostTime;
+	IMG_UINT32 ui32SGXClocksx16;
+} PVRSRV_SYSTRACE_TIMECORR;
+
+typedef struct _PVRSRV_SYSTRACE_DATA_
+{
+	IMG_UINT32 ui32Index;
+	IMG_UINT32 ui32CurrentCtxID;
+
+	PVRSRV_SYSTRACE_CONTEXT asSystraceContext[8];
+	PVRSRV_SYSTRACE_TIMECORR asTimeCorrArray[32]; /* Array to store HostTime and corresponding SGXClks (Max value is PVRSRV_SYSTRACE_TIMEINDEX_LIMIT set in systrace.c */
+	IMG_UINT32 ui32TimeCorrIndex;				  /* Global current index */
+
+	IMG_BOOL bLastPowerDown;					  /* During last MISR Device was powered off */
+} PVRSRV_SYSTRACE_DATA;	
+#endif
+
+typedef struct _PVRSRV_SGX_CCB_INFO_ *PPVRSRV_SGX_CCB_INFO;
+
+typedef struct _PVRSRV_SGXDEV_INFO_
+{
+	PVRSRV_DEVICE_TYPE		eDeviceType;
+	PVRSRV_DEVICE_CLASS		eDeviceClass;
+
+	IMG_UINT8				ui8VersionMajor;
+	IMG_UINT8				ui8VersionMinor;
+	IMG_UINT32				ui32CoreConfig;
+	IMG_UINT32				ui32CoreFlags;
+
+	/* Kernel mode linear address of device registers */
+	IMG_PVOID				pvRegsBaseKM;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	/* Kernel mode linear address of host port */
+	IMG_PVOID				pvHostPortBaseKM;
+	/* HP size */
+	IMG_UINT32				ui32HPSize;
+	/* HP syspaddr */
+	IMG_SYS_PHYADDR			sHPSysPAddr;
+#endif
+
+	/* FIXME: The alloc for this should go through OSAllocMem in future */
+	IMG_HANDLE				hRegMapping;
+
+	/* System physical address of device registers*/
+	IMG_SYS_PHYADDR			sRegsPhysBase;
+	/*  Register region size in bytes */
+	IMG_UINT32				ui32RegSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+	/* external system cache register region size in bytes */
+	IMG_UINT32				ui32ExtSysCacheRegsSize;
+	/* external system cache register device relative physical address */
+	IMG_DEV_PHYADDR			sExtSysCacheRegsDevPBase;
+	/* ptr to page table  */
+	IMG_UINT32				*pui32ExtSystemCacheRegsPT;
+	/* handle to page table alloc/mapping */
+	IMG_HANDLE				hExtSystemCacheRegsPTPageOSMemHandle;
+	/* sys phys addr of PT */
+	IMG_SYS_PHYADDR			sExtSystemCacheRegsPTSysPAddr;
+#endif
+
+	/*  SGX clock speed */
+	IMG_UINT32				ui32CoreClockSpeed;
+	IMG_UINT32				ui32uKernelTimerClock;
+	IMG_BOOL				bSGXIdle;
+
+	PVRSRV_STUB_PBDESC		*psStubPBDescListKM;
+
+
+	/* kernel memory context info */
+	IMG_DEV_PHYADDR			sKernelPDDevPAddr;
+
+	IMG_UINT32				ui32HeapCount;			/*!< heap count */
+	IMG_VOID				*pvDeviceMemoryHeap;
+	PPVRSRV_KERNEL_MEM_INFO	psKernelCCBMemInfo;			/*!< meminfo for CCB in device accessible memory */
+	PVRSRV_SGX_KERNEL_CCB	*psKernelCCB;			/*!< kernel mode linear address of CCB in device accessible memory */
+	PPVRSRV_SGX_CCB_INFO	psKernelCCBInfo;		/*!< CCB information structure */
+	PPVRSRV_KERNEL_MEM_INFO	psKernelCCBCtlMemInfo;	/*!< meminfo for CCB control in device accessible memory */
+	PVRSRV_SGX_CCB_CTL		*psKernelCCBCtl;		/*!< kernel mode linear address of CCB control in device accessible memory */
+	PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo; /*!< meminfo for kernel CCB event kicker */
+	IMG_UINT32				*pui32KernelCCBEventKicker; /*!< kernel mode linear address of kernel CCB event kicker */
+#if defined(PDUMP)
+	IMG_UINT32				ui32KernelCCBEventKickerDumpVal; /*!< pdump copy of the kernel CCB event kicker */
+#endif /* PDUMP */
+ 	PVRSRV_KERNEL_MEM_INFO	*psKernelSGXMiscMemInfo;	/*!< kernel mode linear address of SGX misc info buffer */
+	IMG_UINT32				aui32HostKickAddr[SGXMKIF_CMD_MAX];		/*!< ukernel host kick offests */
+#if defined(SGX_SUPPORT_HWPROFILING)
+	PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
+#endif
+	PPVRSRV_KERNEL_MEM_INFO		psKernelHWPerfCBMemInfo;		/*!< Meminfo for hardware performace circular buffer */
+	PPVRSRV_KERNEL_MEM_INFO		psKernelTASigBufferMemInfo;		/*!< Meminfo for TA signature buffer */
+	PPVRSRV_KERNEL_MEM_INFO		psKernel3DSigBufferMemInfo;		/*!< Meminfo for 3D signature buffer */
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+	defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+	PPVRSRV_KERNEL_MEM_INFO	psKernelVDMStateUpdateBufferMemInfo; /*!< Meminfo for state update buffer */
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	PPVRSRV_KERNEL_MEM_INFO	psKernelEDMStatusBufferMemInfo; /*!< Meminfo for EDM status buffer */
+#endif
+	/* Client reference count */
+	IMG_UINT32				ui32ClientRefCount;
+
+	/* cache control word for micro kernel cache flush/invalidates */
+	IMG_UINT32				ui32CacheControl;
+
+	/* client-side build options */
+	IMG_UINT32				ui32ClientBuildOptions;
+
+	/* client-side microkernel structure sizes */
+	SGX_MISCINFO_STRUCT_SIZES	sSGXStructSizes;
+
+	/*
+		if we don't preallocate the pagetables we must 
+		insert newly allocated page tables dynamically 
+	*/
+	IMG_VOID				*pvMMUContextList;
+
+	/* Copy of registry ForcePTOff entry */
+	IMG_BOOL				bForcePTOff;
+
+	IMG_UINT32				ui32EDMTaskReg0;
+	IMG_UINT32				ui32EDMTaskReg1;
+
+	IMG_UINT32				ui32ClkGateCtl;
+	IMG_UINT32				ui32ClkGateCtl2;
+	IMG_UINT32				ui32ClkGateStatusReg;
+	IMG_UINT32				ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+	IMG_UINT32				ui32MasterClkGateStatusReg;
+	IMG_UINT32				ui32MasterClkGateStatusMask;
+	IMG_UINT32				ui32MasterClkGateStatus2Reg;
+	IMG_UINT32				ui32MasterClkGateStatus2Mask;
+#endif /* SGX_FEATURE_MP */
+#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+	IMG_BOOL				bDisableClockGating;
+#endif
+	SGX_INIT_SCRIPTS		sScripts;
+
+	/* Members associated with dummy PD needed for BIF reset */
+	IMG_HANDLE 				hBIFResetPDOSMemHandle;
+	IMG_DEV_PHYADDR 		sBIFResetPDDevPAddr;
+	IMG_DEV_PHYADDR 		sBIFResetPTDevPAddr;
+	IMG_DEV_PHYADDR 		sBIFResetPageDevPAddr;
+	IMG_UINT32				*pui32BIFResetPD;
+	IMG_UINT32				*pui32BIFResetPT;
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+	/* Timeout callback handle */
+	IMG_HANDLE				hTimer;
+	/* HW recovery Time stamp */
+	IMG_UINT32				ui32TimeStamp;
+#endif
+
+	/* Number of SGX resets */
+	IMG_UINT32				ui32NumResets;
+
+	/* host control */
+	PVRSRV_KERNEL_MEM_INFO			*psKernelSGXHostCtlMemInfo;
+	SGXMKIF_HOST_CTL				*psSGXHostCtl;
+
+	/* TA/3D control */
+	PVRSRV_KERNEL_MEM_INFO			*psKernelSGXTA3DCtlMemInfo;
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+	PVRSRV_KERNEL_MEM_INFO			*psKernelSGXPTLAWriteBackMemInfo;
+#endif
+
+	/* memory tiling range usage */
+	IMG_UINT32				ui32MemTilingUsage;
+
+	#if defined(PDUMP)
+	PVRSRV_SGX_PDUMP_CONTEXT	sPDContext;
+	#endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+	/* SGX MMU dummy page details */
+	IMG_VOID				*pvDummyPTPageCpuVAddr;
+	IMG_DEV_PHYADDR			sDummyPTDevPAddr;
+	IMG_HANDLE				hDummyPTPageOSMemHandle;
+	IMG_VOID				*pvDummyDataPageCpuVAddr;
+	IMG_DEV_PHYADDR 		sDummyDataDevPAddr;
+	IMG_HANDLE				hDummyDataPageOSMemHandle;
+#endif
+#if defined(PDUMP)
+	PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+	IMG_UINT32				asSGXDevData[SGX_MAX_DEV_DATA];
+
+#if defined(FIX_HW_BRN_31620)
+	/* Dummy page refs */
+	IMG_VOID			*pvBRN31620DummyPageCpuVAddr;
+	IMG_HANDLE			hBRN31620DummyPageOSMemHandle;
+	IMG_DEV_PHYADDR			sBRN31620DummyPageDevPAddr;
+
+	/* Dummy PT refs */
+	IMG_VOID			*pvBRN31620DummyPTCpuVAddr;
+	IMG_HANDLE			hBRN31620DummyPTOSMemHandle;
+	IMG_DEV_PHYADDR			sBRN31620DummyPTDevPAddr;
+
+	IMG_HANDLE			hKernelMMUContext;
+#endif
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	IMG_BOOL			bSystraceInitialised;
+	PVRSRV_SYSTRACE_DATA *psSystraceData;
+#endif
+
+} PVRSRV_SGXDEV_INFO;
+
+
+typedef struct _SGX_TIMING_INFORMATION_
+{
+	IMG_UINT32			ui32CoreClockSpeed;
+	IMG_UINT32			ui32HWRecoveryFreq;
+	IMG_BOOL			bEnableActivePM;
+	IMG_UINT32			ui32ActivePowManLatencyms;
+	IMG_UINT32			ui32uKernelFreq;
+} SGX_TIMING_INFORMATION;
+
+/* FIXME Rename this structure to sg more generalised as it's been extended*/
+/* SGX device map */
+typedef struct _SGX_DEVICE_MAP_
+{
+	IMG_UINT32				ui32Flags;
+
+	/* Registers */
+	IMG_SYS_PHYADDR			sRegsSysPBase;
+	IMG_CPU_PHYADDR			sRegsCpuPBase;
+	IMG_CPU_VIRTADDR		pvRegsCpuVBase;
+	IMG_UINT32				ui32RegsSize;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	IMG_SYS_PHYADDR			sHPSysPBase;
+	IMG_CPU_PHYADDR			sHPCpuPBase;
+	IMG_UINT32				ui32HPSize;
+#endif
+
+	/* Local Device Memory Region: (if present) */
+	IMG_SYS_PHYADDR			sLocalMemSysPBase;
+	IMG_DEV_PHYADDR			sLocalMemDevPBase;
+	IMG_CPU_PHYADDR			sLocalMemCpuPBase;
+	IMG_UINT32				ui32LocalMemSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+	IMG_UINT32				ui32ExtSysCacheRegsSize;
+	IMG_DEV_PHYADDR			sExtSysCacheRegsDevPBase;
+#endif
+
+	/* device interrupt IRQ */
+	IMG_UINT32				ui32IRQ;
+
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+	/* timing information*/
+	SGX_TIMING_INFORMATION	sTimingInfo;
+#endif
+#if defined(PDUMP)
+	/* pdump memory region name */
+	IMG_CHAR				*pszPDumpDevName;
+#endif
+} SGX_DEVICE_MAP;
+
+
+struct _PVRSRV_STUB_PBDESC_
+{
+	IMG_UINT32		ui32RefCount;
+	IMG_UINT32		ui32TotalPBSize;
+	PVRSRV_KERNEL_MEM_INFO  *psSharedPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO  *psHWPBDescKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO	**ppsSubKernelMemInfos;
+	IMG_UINT32		ui32SubKernelMemInfosCount;
+	IMG_HANDLE		hDevCookie;
+	PVRSRV_KERNEL_MEM_INFO  *psBlockKernelMemInfo;
+	PVRSRV_KERNEL_MEM_INFO  *psHWBlockKernelMemInfo;
+	IMG_DEV_VIRTADDR	sHWPBDescDevVAddr;
+	PVRSRV_STUB_PBDESC	*psNext;
+	PVRSRV_STUB_PBDESC	**ppsThis;
+};
+
+/*!
+ ******************************************************************************
+ * CCB control structure for SGX
+ *****************************************************************************/
+typedef struct _PVRSRV_SGX_CCB_INFO_
+{
+	PVRSRV_KERNEL_MEM_INFO	*psCCBMemInfo;			/*!< meminfo for CCB in device accessible memory */
+	PVRSRV_KERNEL_MEM_INFO	*psCCBCtlMemInfo;		/*!< meminfo for CCB control in device accessible memory */
+	SGXMKIF_COMMAND		*psCommands;			/*!< linear address of the array of commands */
+	IMG_UINT32				*pui32WriteOffset;		/*!< linear address of the write offset into array of commands */
+	volatile IMG_UINT32		*pui32ReadOffset;		/*!< linear address of the read offset into array of commands */
+#if defined(PDUMP)
+	IMG_UINT32				ui32CCBDumpWOff;		/*!< for pdumping */
+#endif
+} PVRSRV_SGX_CCB_INFO;
+
+
+typedef struct _SGX_BRIDGE_INIT_INFO_KM_
+{
+	IMG_HANDLE	hKernelCCBMemInfo;
+	IMG_HANDLE	hKernelCCBCtlMemInfo;
+	IMG_HANDLE	hKernelCCBEventKickerMemInfo;
+	IMG_HANDLE	hKernelSGXHostCtlMemInfo;
+	IMG_HANDLE	hKernelSGXTA3DCtlMemInfo;
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+	IMG_HANDLE	hKernelSGXPTLAWriteBackMemInfo;
+#endif
+	IMG_HANDLE	hKernelSGXMiscMemInfo;
+
+	IMG_UINT32	aui32HostKickAddr[SGXMKIF_CMD_MAX];
+
+	SGX_INIT_SCRIPTS sScripts;
+
+	IMG_UINT32	ui32ClientBuildOptions;
+	SGX_MISCINFO_STRUCT_SIZES	sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	IMG_HANDLE	hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+	IMG_HANDLE	hKernelHWPerfCBMemInfo;
+#endif
+	IMG_HANDLE	hKernelTASigBufferMemInfo;
+	IMG_HANDLE	hKernel3DSigBufferMemInfo;
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	IMG_HANDLE	hKernelEDMStatusBufferMemInfo;
+#endif
+
+	IMG_UINT32 ui32EDMTaskReg0;
+	IMG_UINT32 ui32EDMTaskReg1;
+
+	IMG_UINT32 ui32ClkGateStatusReg;
+	IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+//	IMG_UINT32 ui32MasterClkGateStatusReg;
+//	IMG_UINT32 ui32MasterClkGateStatusMask;
+//	IMG_UINT32 ui32MasterClkGateStatus2Reg;
+//	IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif /* SGX_FEATURE_MP */
+
+	IMG_UINT32 ui32CacheControl;
+
+	IMG_UINT32	asInitDevData[SGX_MAX_DEV_DATA];
+	IMG_HANDLE	asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+} SGX_BRIDGE_INIT_INFO_KM;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_KM_
+{
+	CTL_STATUS				sCtlStatus;
+	IMG_HANDLE				hKernelMemInfo;
+} SGX_INTERNEL_STATUS_UPDATE_KM;
+
+
+typedef struct _SGX_CCB_KICK_KM_
+{
+	SGXMKIF_COMMAND		sCommand;
+	IMG_HANDLE	hCCBKernelMemInfo;
+
+	IMG_UINT32	ui32NumDstSyncObjects;
+	IMG_HANDLE	hKernelHWSyncListMemInfo;
+
+	/* DST syncs */
+	IMG_HANDLE	*pahDstSyncHandles;
+
+	IMG_UINT32	ui32NumTAStatusVals;
+	IMG_UINT32	ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+	SGX_INTERNEL_STATUS_UPDATE_KM	asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+	SGX_INTERNEL_STATUS_UPDATE_KM	as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+	IMG_HANDLE	ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+	IMG_HANDLE	ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+
+	IMG_BOOL	bFirstKickOrResume;
+#if defined(NO_HARDWARE) || defined(PDUMP)
+	IMG_BOOL	bTerminateOrAbort;
+#endif
+
+	/* CCB offset of data structure associated with this kick */
+	IMG_UINT32	ui32CCBOffset;
+
+	/* SRC syncs */
+	IMG_UINT32	ui32NumSrcSyncs;
+	IMG_HANDLE	ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+
+	/* TA/3D dependency data */
+	IMG_BOOL	bTADependency;
+	IMG_HANDLE	hTA3DSyncInfo;
+
+	IMG_HANDLE	hTASyncInfo;
+	IMG_HANDLE	h3DSyncInfo;
+#if defined(PDUMP)
+	IMG_UINT32	ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+	IMG_UINT32	ui32WriteOpsPendingVal;
+#endif
+} SGX_CCB_KICK_KM;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct _PVRSRV_TRANSFER_SGX_KICK_KM_
+{
+	IMG_HANDLE		hCCBMemInfo;
+	IMG_UINT32		ui32SharedCmdCCBOffset;
+
+	IMG_DEV_VIRTADDR 	sHWTransferContextDevVAddr;
+
+	IMG_HANDLE		hTASyncInfo;
+	IMG_HANDLE		h3DSyncInfo;
+
+	IMG_UINT32		ui32NumSrcSync;
+	IMG_HANDLE		ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+	IMG_UINT32		ui32NumDstSync;
+	IMG_HANDLE		ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+	IMG_UINT32		ui32Flags;
+
+	IMG_UINT32		ui32PDumpFlags;
+#if defined(PDUMP)
+	IMG_UINT32		ui32CCBDumpWOff;
+#endif
+} PVRSRV_TRANSFER_SGX_KICK_KM, *PPVRSRV_TRANSFER_SGX_KICK_KM;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVRSRV_2D_SGX_KICK_KM_
+{
+	IMG_HANDLE		hCCBMemInfo;
+	IMG_UINT32		ui32SharedCmdCCBOffset;
+
+	IMG_DEV_VIRTADDR 	sHW2DContextDevVAddr;
+
+	IMG_UINT32		ui32NumSrcSync;
+	IMG_HANDLE		ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+	/* need to be able to check reads and writes on dest, and update writes */
+	IMG_HANDLE 		hDstSyncInfo;
+
+	/* need to be able to check reads and writes on TA ops, and update writes */
+	IMG_HANDLE		hTASyncInfo;
+
+	/* need to be able to check reads and writes on 2D ops, and update writes */
+	IMG_HANDLE		h3DSyncInfo;
+
+	IMG_UINT32		ui32PDumpFlags;
+#if defined(PDUMP)
+	IMG_UINT32		ui32CCBDumpWOff;
+#endif
+} PVRSRV_2D_SGX_KICK_KM, *PPVRSRV_2D_SGX_KICK_KM;
+#endif	/* defined(SGX_FEATURE_2D_HARDWARE) */
+#endif /* #if defined(TRANSFER_QUEUE) */
+
+/****************************************************************************/
+/* kernel only functions prototypes 										*/
+/****************************************************************************/
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SGXOSTimer(IMG_VOID *pvData);
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO	*psDevInfo,
+				  IMG_BOOL				bHardwareRecovery,
+				  IMG_UINT32			ui32PDUMPFlags);
+
+IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO	*psDevInfo,
+					   IMG_UINT32			ui32PDUMPFlags);
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO	*psDevInfo,
+						   IMG_BOOL				bHardwareRecovery);
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+
+PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE				hDevHandle, 
+							  PVRSRV_DEV_POWER_STATE	eNewPowerState, 
+							  PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE				hDevHandle, 
+							   PVRSRV_DEV_POWER_STATE	eNewPowerState, 
+							   PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE				hDevHandle,
+									IMG_BOOL				bIdleDevice,
+									PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE				hDevHandle,
+									 IMG_BOOL				bIdleDevice,
+									 PVRSRV_DEV_POWER_STATE	eCurrentPowerState);
+
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO	*psDevInfo);
+
+IMG_VOID RunSGXREGDebugScripts(PVRSRV_SGXDEV_INFO	*psDevInfo);
+
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO	*psDevInfo,
+						   IMG_BOOL				bDumpSGXRegs);
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
+#endif
+
+/****************************************************************************/
+/* kernel only functions: 													*/
+/****************************************************************************/
+#if defined(NO_HARDWARE)
+static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO		*psDevInfo,
+												IMG_UINT32 ui32StatusRegister,
+												IMG_UINT32 ui32StatusValue,
+												IMG_UINT32 ui32StatusMask)
+{
+	IMG_UINT32 ui32RegVal;
+
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister);
+
+	ui32RegVal &= ~ui32StatusMask;
+	ui32RegVal |= (ui32StatusValue & ui32StatusMask);
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __SGXINFOKM_H__ */
+
+/*****************************************************************************
+ End of file (sgxinfokm.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxinit.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxinit.c
new file mode 100644
index 0000000..0277ac6
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxinit.c
@@ -0,0 +1,3642 @@
+/*************************************************************************/ /*!
+@Title          Device specific initialisation routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+
+#include "sgx_bridge_km.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+
+#include "lists.h"
+#include "srvkm.h"
+#include "ttrace.h"
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+#include "systrace.h"
+#endif
+
+IMG_UINT32 g_ui32HostIRQCountSample = 0;
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+
+static const IMG_CHAR *SGXUKernelStatusString(IMG_UINT32 code)
+{
+	switch(code)
+	{
+#define MKTC_ST(x) \
+		case x: \
+			return #x;
+#include "sgx_ukernel_status_codes.h"
+		default:
+			return "(Unknown)";
+	}
+}
+
+#endif /* defined(PVRSRV_USSE_EDM_STATUS_DEBUG) */
+
+#define VAR(x) #x
+/* PRQA S 0881 11 */ /* ignore 'order of evaluation' warning */
+#define CHECK_SIZE(NAME) \
+{	\
+	if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
+	{	\
+		PVR_DPF((PVR_DBG_ERROR, "SGXDevInitCompatCheck: Size check failed for SGXMKIF_%s (client) = %d bytes, (ukernel) = %d bytes\n", \
+			VAR(NAME), \
+			psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME, \
+			psSGXStructSizes->ui32Sizeof_##NAME )); \
+		bStructSizesFailed = IMG_TRUE; \
+	}	\
+}
+
+#if defined (SYS_USING_INTERRUPTS)
+IMG_BOOL SGX_ISRHandler(IMG_VOID *pvData);
+#endif
+
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO	*psDevInfo,
+								   PVRSRV_DEVICE_NODE 	*psDeviceNode,
+								   IMG_HANDLE hDevMemContext);
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function	SGXCommandComplete
+
+ @Description
+
+ SGX command complete handler
+
+ @Input psDeviceNode - SGX device node
+
+ @Return none
+
+******************************************************************************/
+static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(OS_SUPPORTS_IN_LISR)
+	if (OSInLISR(psDeviceNode->psSysData))
+	{
+		/*
+		 * We shouldn't call SGXScheduleProcessQueuesKM in an
+		 * LISR, as it may attempt to power up SGX.
+		 * We assume that the LISR will schedule the MISR, which
+		 * will test the following flag, and call
+		 * SGXScheduleProcessQueuesKM if the flag is set.
+		 */
+		psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+	}
+	else
+	{
+		SGXScheduleProcessQueuesKM(psDeviceNode);
+	}
+#else
+	SGXScheduleProcessQueuesKM(psDeviceNode);
+#endif
+}
+
+/*!
+*******************************************************************************
+
+ @Function	DeinitDevInfo
+
+ @Description
+
+ Deinits DevInfo
+
+ @Input none
+
+ @Return none
+
+******************************************************************************/
+static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	if (psDevInfo->psKernelCCBInfo != IMG_NULL)
+	{
+		/*
+			Free CCB info.
+		*/
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function	InitDevInfo
+
+ @Description
+
+ Loads DevInfo
+
+ @Input psDeviceNode
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
+								PVRSRV_DEVICE_NODE *psDeviceNode,
+								SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+	PVRSRV_ERROR		eError;
+
+	PVRSRV_SGX_CCB_INFO	*psKernelCCBInfo = IMG_NULL;
+
+	PVR_UNREFERENCED_PARAMETER(psPerProc);
+	psDevInfo->sScripts = psInitInfo->sScripts;
+
+	psDevInfo->psKernelCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
+	psDevInfo->psKernelCCB = (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelCCBCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
+	psDevInfo->psKernelCCBCtl = (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelCCBEventKickerMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBEventKickerMemInfo;
+	psDevInfo->pui32KernelCCBEventKicker = (IMG_UINT32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelSGXHostCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXHostCtlMemInfo;
+	psDevInfo->psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+	psDevInfo->psKernelSGXTA3DCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXTA3DCtlMemInfo;
+
+#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
+	psDevInfo->psKernelSGXPTLAWriteBackMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXPTLAWriteBackMemInfo;
+#endif
+
+	psDevInfo->psKernelSGXMiscMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+	psDevInfo->psKernelHWProfilingMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+	psDevInfo->psKernelHWPerfCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+#endif
+	psDevInfo->psKernelTASigBufferMemInfo = psInitInfo->hKernelTASigBufferMemInfo;
+	psDevInfo->psKernel3DSigBufferMemInfo = psInitInfo->hKernel3DSigBufferMemInfo;
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
+	defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
+	psDevInfo->psKernelVDMStateUpdateBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMStateUpdateBufferMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
+#endif
+	/*
+	 * 	Assign client-side build options for later verification
+	 */
+	psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
+
+	/*
+	 * 	Assign microkernel IF structure sizes for later verification
+	 */
+	psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
+
+	/*
+		Setup the kernel version of the CCB control
+	*/
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+						sizeof(PVRSRV_SGX_CCB_INFO),
+						(IMG_VOID **)&psKernelCCBInfo, 0,
+						"SGX Circular Command Buffer Info");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory"));
+		goto failed_allockernelccb;
+	}
+
+
+	OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
+	psKernelCCBInfo->psCCBMemInfo		= psDevInfo->psKernelCCBMemInfo;
+	psKernelCCBInfo->psCCBCtlMemInfo	= psDevInfo->psKernelCCBCtlMemInfo;
+	psKernelCCBInfo->psCommands			= psDevInfo->psKernelCCB->asCommands;
+	psKernelCCBInfo->pui32WriteOffset	= &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+	psKernelCCBInfo->pui32ReadOffset	= &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+	psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
+
+	/*
+		Copy the USE code addresses for the host kick.
+	*/
+	OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
+			  SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
+
+ 	psDevInfo->bForcePTOff = IMG_FALSE;
+
+	psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+	psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+	psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+	psDevInfo->ui32ClkGateCtl = psInitInfo->ui32ClkGateCtl;
+	psDevInfo->ui32ClkGateCtl2 = psInitInfo->ui32ClkGateCtl2;
+	psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
+	psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+	psDevInfo->ui32MasterClkGateStatusReg = psInitInfo->ui32MasterClkGateStatusReg;
+	psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
+	psDevInfo->ui32MasterClkGateStatus2Reg = psInitInfo->ui32MasterClkGateStatus2Reg;
+	psDevInfo->ui32MasterClkGateStatus2Mask = psInitInfo->ui32MasterClkGateStatus2Mask;
+#endif /* SGX_FEATURE_MP */
+#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+	psDevInfo->bDisableClockGating = psInitInfo->bDisableClockGating;
+#endif
+
+
+	/* Initialise Dev Data */
+	OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
+
+	return PVRSRV_OK;
+
+failed_allockernelccb:
+	DeinitDevInfo(psDevInfo);
+
+	return eError;
+}
+
+
+
+
+static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands)
+{
+	IMG_UINT32 ui32PC;
+	SGX_INIT_COMMAND *psComm;
+
+	for (ui32PC = 0, psComm = psScript;
+		ui32PC < ui32NumInitCommands;
+		ui32PC++, psComm++)
+	{
+		switch (psComm->eOp)
+		{
+			case SGX_INIT_OP_WRITE_HW_REG:
+			{
+				OSWriteHWReg(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+				PDUMPCOMMENT("SGXRunScript: Write HW reg operation");
+				PDUMPREG(SGX_PDUMPREG_NAME, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+				break;
+			}
+			case SGX_INIT_OP_READ_HW_REG:
+			{
+				psComm->sReadHWReg.ui32Value = OSReadHWReg(psDevInfo->pvRegsBaseKM, psComm->sReadHWReg.ui32Offset);
+#if defined(PDUMP)
+				PDUMPCOMMENT("SGXRunScript: Read HW reg operation");
+				PDumpRegRead(SGX_PDUMPREG_NAME, psComm->sReadHWReg.ui32Offset, PDUMP_FLAGS_CONTINUOUS);
+#endif
+				break;
+			}
+			case SGX_INIT_OP_PRINT_HW_REG:
+			{
+				psComm->sReadHWReg.ui32Value = OSReadHWReg(psDevInfo->pvRegsBaseKM, psComm->sReadHWReg.ui32Offset);
+				PVR_LOG(("\t(SGXREG) 0x%08X : 0x%08X", psComm->sReadHWReg.ui32Offset, psComm->sReadHWReg.ui32Value));
+
+				break;
+			}
+
+#if defined(PDUMP)
+			case SGX_INIT_OP_PDUMP_HW_REG:
+			{
+				PDUMPCOMMENT("SGXRunScript: Dump HW reg operation");
+				PDUMPREG(SGX_PDUMPREG_NAME, psComm->sPDumpHWReg.ui32Offset, psComm->sPDumpHWReg.ui32Value);
+				break;
+			}
+#endif
+			case SGX_INIT_OP_HALT:
+			{
+				return PVRSRV_OK;
+			}
+			case SGX_INIT_OP_ILLEGAL:
+			/* FALLTHROUGH */
+			default:
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+				return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+			}
+		}
+
+	}
+
+	return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+}
+
+/* Run scripts on given core */
+static PVRSRV_ERROR SGXRunScriptOnCore(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands, IMG_UINT32 ui32CoreNum)
+{
+	IMG_UINT32 ui32PC;
+	SGX_INIT_COMMAND *psComm;
+
+#if !defined(SGX_FEATURE_MP)
+	PVR_UNREFERENCED_PARAMETER(ui32CoreNum);
+#endif
+
+	for (ui32PC = 0, psComm = psScript;
+		ui32PC < ui32NumInitCommands;
+		ui32PC++, psComm++)
+	{
+		switch (psComm->eOp)
+		{
+			case SGX_INIT_OP_WRITE_HW_REG:
+			{
+				OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(psComm->sWriteHWReg.ui32Offset,ui32CoreNum), psComm->sWriteHWReg.ui32Value);
+				PDUMPCOMMENT("SGXRunScriptOnCore: Write HW reg operation");
+				PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(psComm->sWriteHWReg.ui32Offset,ui32CoreNum), psComm->sWriteHWReg.ui32Value);
+				break;
+			}
+			case SGX_INIT_OP_READ_HW_REG:
+			{
+				psComm->sReadHWReg.ui32Value = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(psComm->sReadHWReg.ui32Offset, ui32CoreNum));
+#if defined(PDUMP)
+				PDUMPCOMMENT("SGXRunScriptOnCore: Read HW reg operation");
+				PDumpRegRead(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(psComm->sReadHWReg.ui32Offset,ui32CoreNum), PDUMP_FLAGS_CONTINUOUS);
+#endif
+				break;
+			}
+			case SGX_INIT_OP_PRINT_HW_REG:
+			{
+				psComm->sReadHWReg.ui32Value = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(psComm->sReadHWReg.ui32Offset,ui32CoreNum));
+				PVR_LOG(("\t(SGXREG) 0x%08X : 0x%08X", SGX_MP_CORE_SELECT(psComm->sReadHWReg.ui32Offset, ui32CoreNum), psComm->sReadHWReg.ui32Value));
+
+				break;
+			}
+
+#if defined(PDUMP)
+			case SGX_INIT_OP_PDUMP_HW_REG:
+			{
+				PDUMPCOMMENT("SGXRunScriptOnCore: Dump HW reg operation");
+				PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(psComm->sPDumpHWReg.ui32Offset, ui32CoreNum), psComm->sPDumpHWReg.ui32Value);
+				break;
+			}
+#endif
+			case SGX_INIT_OP_HALT:
+			{
+				return PVRSRV_OK;
+			}
+			case SGX_INIT_OP_ILLEGAL:
+			/* FALLTHROUGH */
+			default:
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXRunScriptOnCore: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+				return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+			}
+		}
+
+	}
+
+	return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+}
+
+#if defined(SUPPORT_MEMORY_TILING)
+static PVRSRV_ERROR SGX_AllocMemTilingRangeInt(PVRSRV_SGXDEV_INFO *psDevInfo,
+											   IMG_UINT32 ui32Start,
+											   IMG_UINT32 ui32End,
+										IMG_UINT32 ui32TilingStride,
+										IMG_UINT32 *pui32RangeIndex)
+{
+	IMG_UINT32 i;
+	IMG_UINT32 ui32Offset;
+	IMG_UINT32 ui32Val;
+
+	/* HW supports 10 ranges */
+	for(i=0; i < SGX_BIF_NUM_TILING_RANGES; i++)
+	{
+		if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
+		{
+			/* mark in use */
+			psDevInfo->ui32MemTilingUsage |= 1U << i;
+			/* output range index if the caller wants it */
+			if(pui32RangeIndex != IMG_NULL)
+			{
+				*pui32RangeIndex = i;
+			}
+			goto RangeAllocated;
+		}
+	}
+
+	PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
+	return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
+
+RangeAllocated:
+
+	/* An improperly aligned range could cause BIF not to tile some memory which is intended to be tiled,
+	 * or cause BIF to tile some memory which is not intended to be.
+	 */
+	if(ui32Start & ~SGX_BIF_TILING_ADDR_MASK)
+	{
+		PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range start (0x%08X) fails"
+						"alignment test", ui32Start));
+	}
+	if((ui32End + 0x00001000) & ~SGX_BIF_TILING_ADDR_MASK)
+	{
+		PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range end (0x%08X) fails"
+						"alignment test", ui32End));
+	}
+
+	ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
+
+	ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
+			| (((ui32End>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
+			| (((ui32Start>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
+			| (EUR_CR_BIF_TILE0_ENABLE << EUR_CR_BIF_TILE0_CFG_SHIFT);
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+	PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+	ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
+
+	ui32Val = (((ui32End>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
+			| (((ui32Start>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+	PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+#endif /* SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS */
+
+	return PVRSRV_OK;
+}
+
+#endif /* SUPPORT_MEMORY_TILING */
+
+/*!
+*******************************************************************************
+
+ @Function	SGXInitialise
+
+ @Description
+
+ (client invoked) chip-reset and initialisation
+
+ @Input pvDeviceNode - device info. structure
+ @Input bHardwareRecovery - true if recovering powered hardware,
+ 							false if powering up
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO	*psDevInfo,
+						   IMG_BOOL				bHardwareRecovery)
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_KERNEL_MEM_INFO	*psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+	SGXMKIF_HOST_CTL		*psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+	static IMG_BOOL			bFirstTime = IMG_TRUE;
+#if defined(PDUMP)
+	IMG_BOOL				bPDumpIsSuspended = PDumpIsSuspended();
+#endif /* PDUMP */
+
+#if defined(SGX_FEATURE_MP)
+	/* Slave core clocks must be enabled during reset */
+#else
+	SGXInitClocks(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
+#endif /* SGX_FEATURE_MP */
+	
+	/*
+		Part 1 of the initialisation script runs before resetting SGX.
+	*/
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
+	eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 1) failed (%d)", eError));
+		return eError;
+	}
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
+
+	/* Reset the chip */
+	psDevInfo->ui32NumResets++;
+	
+#if !defined(SGX_FEATURE_MP)
+	bHardwareRecovery |= bFirstTime;
+#endif /* SGX_FEATURE_MP */
+	
+	SGXReset(psDevInfo, bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(EUR_CR_POWER)
+#if defined(SGX531)
+	/*
+		Disable half the pipes.
+		531 has 2 pipes within a 4 pipe framework, so 
+		the 2 redundant pipes must be disabled even
+		though they do not exist.
+	*/
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
+	PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1);
+#else
+	/* set the default pipe count (all fully enabled) */
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
+	PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0);
+#endif
+#endif
+
+	/* Initialise the kernel CCB event kicker value */
+	*psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+	if (!bPDumpIsSuspended)
+	{
+		psDevInfo->ui32KernelCCBEventKickerDumpVal = 0;
+		PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+				 psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+				 sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
+				 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+	}
+#endif /* PDUMP */
+
+#if defined(SUPPORT_MEMORY_TILING)
+	{
+		/* Initialise EUR_CR_BIF_TILE registers for any tiling heaps */
+		DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDevInfo->pvDeviceMemoryHeap;
+		IMG_UINT32 i;
+
+		psDevInfo->ui32MemTilingUsage = 0;
+
+		for(i=0; i<psDevInfo->ui32HeapCount; i++)
+		{
+			if(psDeviceMemoryHeap[i].ui32XTileStride > 0)
+			{
+				/* Set up the HW control registers */
+				eError = SGX_AllocMemTilingRangeInt(
+						psDevInfo,
+						psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr,
+						psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr
+							+ psDeviceMemoryHeap[i].ui32HeapSize,
+						psDeviceMemoryHeap[i].ui32XTileStride,
+						NULL);
+				if(eError != PVRSRV_OK)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "Unable to allocate SGX BIF tiling range for heap: %s",
+											psDeviceMemoryHeap[i].pszName));
+					break;
+				}
+			}
+		}
+	}
+#endif
+
+	/*
+		Part 2 of the initialisation script runs after resetting SGX.
+	*/
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
+	eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 2) failed (%d)", eError));
+		return eError;
+	}
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
+
+	/* Record the system timestamp for the microkernel */
+	psSGXHostCtl->ui32HostClock = OSClockus();
+
+	psSGXHostCtl->ui32InitStatus = 0;
+#if defined(PDUMP)
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+						  "Reset the SGX microkernel initialisation status\n");
+	PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+			 offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+			 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+			 MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+						  "Initialise the microkernel\n");
+#endif /* PDUMP */
+
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+	OSWriteMemoryBarrier();
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				 SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+				 EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+	*psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+	OSWriteMemoryBarrier();
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				 SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+				 EUR_CR_EVENT_KICK_NOW_MASK);
+#endif /* SGX_FEATURE_MULTI_EVENT_KICK */
+
+	OSMemoryBarrier();
+
+#if defined(PDUMP)
+	/*
+		Dump the host kick.
+	*/
+	if (!bPDumpIsSuspended)
+	{
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+		PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+		psDevInfo->ui32KernelCCBEventKickerDumpVal = 1;
+		PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+							  "First increment of the SGX event kicker value\n");
+		PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+				 psDevInfo->psKernelCCBEventKickerMemInfo,
+				 0,
+				 sizeof(IMG_UINT32),
+				 PDUMP_FLAGS_CONTINUOUS,
+				 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+		PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
+#endif /* SGX_FEATURE_MULTI_EVENT_KICK */
+	}
+#endif /* PDUMP */
+
+#if !defined(NO_HARDWARE)
+	/*
+		Wait for the microkernel to finish initialising.
+	*/
+	if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
+					   PVRSRV_USSE_EDM_INIT_COMPLETE,
+					   PVRSRV_USSE_EDM_INIT_COMPLETE,
+					   MAX_HW_TIME_US,
+					   MAX_HW_TIME_US/WAIT_TRY_COUNT,
+					   IMG_FALSE) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
+
+		SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+		PVR_DBG_BREAK;
+
+		return PVRSRV_ERROR_RETRY;
+	}
+#endif /* NO_HARDWARE */
+
+#if defined(PDUMP)
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+						  "Wait for the SGX microkernel initialisation to complete");
+	PDUMPMEMPOL(psSGXHostCtlMemInfo,
+				offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+				PVRSRV_USSE_EDM_INIT_COMPLETE,
+				PVRSRV_USSE_EDM_INIT_COMPLETE,
+				PDUMP_POLL_OPERATOR_EQUAL,
+				PDUMP_FLAGS_CONTINUOUS,
+				MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif /* PDUMP */
+
+	PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+
+	bFirstTime = IMG_FALSE;
+	
+	return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function	SGXDeinitialise
+
+ @Description
+
+ (client invoked) chip-reset and deinitialisation
+
+ @Input hDevCookie - device info. handle
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
+
+{
+	PVRSRV_SGXDEV_INFO	*psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
+	PVRSRV_ERROR		eError;
+
+	/* Did SGXInitialise map the SGX registers in? */
+	if (psDevInfo->pvRegsBaseKM == IMG_NULL)
+	{
+		return PVRSRV_OK;
+	}
+
+	eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands, SGX_MAX_DEINIT_COMMANDS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXDeinitialise: SGXRunScript failed (%d)", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	DevInitSGXPart1
+
+ @Description
+
+ Reset and initialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
+{
+	IMG_HANDLE hDevMemHeap = IMG_NULL;
+	PVRSRV_SGXDEV_INFO	*psDevInfo;
+	IMG_HANDLE		hKernelDevMemContext;
+	IMG_DEV_PHYADDR		sPDDevPAddr;
+	IMG_UINT32		i;
+	PVRSRV_DEVICE_NODE  *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+	PVRSRV_ERROR		eError;
+
+	/* pdump info about the core */
+	PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
+	
+	#if defined(SGX_FEATURE_MP)
+	#if !defined(SGX_FEATURE_MP_PLUS)
+	PDUMPCOMMENT("SGX Multi-processor: %d cores", SGX_FEATURE_MP_CORE_COUNT);
+	#else
+	PDUMPCOMMENT("SGX Multi-processor: %d TA cores, %d 3D cores", SGX_FEATURE_MP_CORE_COUNT_TA, SGX_FEATURE_MP_CORE_COUNT_3D);
+	#endif
+	#endif /* SGX_FEATURE_MP */
+
+#if (SGX_CORE_REV == 0)
+	PDUMPCOMMENT("SGX Core Revision Information: head RTL");
+#else
+	PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
+#endif
+
+	#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	PDUMPCOMMENT("SGX System Level Cache is present\r\n");
+	#if defined(SGX_BYPASS_SYSTEM_CACHE)
+	PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
+	#endif /* SGX_BYPASS_SYSTEM_CACHE */
+	#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+	PDUMPCOMMENT("SGX Initialisation Part 1");
+
+	/* Allocate device control block */
+	if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+					 sizeof(PVRSRV_SGXDEV_INFO),
+					 (IMG_VOID **)&psDevInfo, IMG_NULL,
+					 "SGX Device Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
+
+	/* setup info from jdisplayconfig.h (variations controlled by build) */
+	psDevInfo->eDeviceType 		= DEV_DEVICE_TYPE;
+	psDevInfo->eDeviceClass 	= DEV_DEVICE_CLASS;
+
+	/* Initialize SGX idle status */
+	psDevInfo->bSGXIdle = IMG_TRUE;
+
+	/* Store the devinfo as its needed by dynamically enumerated systems called from BM */
+	psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
+
+	/* get heap info from the devnode */
+	psDevInfo->ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+	psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
+
+	/* create the kernel memory context */
+	hKernelDevMemContext = BM_CreateContext(psDeviceNode,
+											&sPDDevPAddr,
+											IMG_NULL,
+											IMG_NULL);
+	if (hKernelDevMemContext == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1: Failed BM_CreateContext"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+	/* create the kernel, shared and shared_exported heaps */
+	for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
+	{
+		switch(psDeviceMemoryHeap[i].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_KERNEL:
+			case DEVICE_MEMORY_HEAP_SHARED:
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+				/* Shared PB heap could be zero size */
+				if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+				{
+					hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
+												&psDeviceMemoryHeap[i]);
+					/*
+						in the case of kernel context heaps just store
+						the heap handle in the heap info structure
+					*/
+					psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
+				}
+				break;
+			}
+		}
+	}
+#if defined(PDUMP)
+	if(hDevMemHeap)
+	{
+		/* set up the MMU pdump info */
+		psDevInfo->sMMUAttrib = *((BM_HEAP*)hDevMemHeap)->psMMUAttrib;
+	}
+#endif
+	eError = MMU_BIFResetPDAlloc(psDevInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGX : Failed to alloc memory for BIF reset"));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function	SGXGetInfoForSrvinitKM
+
+ @Description
+
+ Get SGX related information necessary for initilisation server
+
+ @Input hDevHandle - device handle
+	psInitInfo - pointer to structure for returned information
+
+ @Output psInitInfo - pointer to structure containing returned information
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+	PVRSRV_SGXDEV_INFO	*psDevInfo;
+	PVRSRV_ERROR		eError;
+
+	PDUMPCOMMENT("SGXGetInfoForSrvinit");
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+	eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)", eError));
+		return eError;
+	}
+
+	return eError;
+}
+
+/*!
+*******************************************************************************
+
+ @Function	DevInitSGXPart2KM
+
+ @Description
+
+ Reset and initialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                IMG_HANDLE hDevHandle,
+                                SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+	PVRSRV_DEVICE_NODE		*psDeviceNode;
+	PVRSRV_SGXDEV_INFO		*psDevInfo;
+	PVRSRV_ERROR			eError;
+	SGX_DEVICE_MAP			*psSGXDeviceMap;
+	PVRSRV_DEV_POWER_STATE	eDefaultPowerState;
+
+	PDUMPCOMMENT("SGX Initialisation Part 2");
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+	/*
+		Init devinfo
+	*/
+	eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to load EDM program"));
+		goto failed_init_dev_info;
+	}
+
+
+	eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+									(IMG_VOID**)&psSGXDeviceMap);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to get device memory map!"));
+		return PVRSRV_ERROR_INIT_FAILURE;
+	}
+
+	/* Registers already mapped? */
+	if (psSGXDeviceMap->pvRegsCpuVBase)
+	{
+		psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
+	}
+	else
+	{
+		/* Map Regs */
+		psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
+											   psSGXDeviceMap->ui32RegsSize,
+											   PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+											   IMG_NULL);
+		if (!psDevInfo->pvRegsBaseKM)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in regs\n"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+	}
+	psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
+	psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+	{
+		/* Map Host Port */
+		psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
+									  	           psSGXDeviceMap->ui32HPSize,
+									  	           PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+									  	           IMG_NULL);
+		if (!psDevInfo->pvHostPortBaseKM)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in host port\n"));
+			return PVRSRV_ERROR_BAD_MAPPING;
+		}
+		psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
+		psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
+	}
+#endif/* #ifdef SGX_FEATURE_HOST_PORT */
+
+#if defined (SYS_USING_INTERRUPTS)
+
+	/* Set up ISR callback information. */
+	psDeviceNode->pvISRData = psDeviceNode;
+	/* ISR handler address was set up earlier */
+	PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+#endif /* SYS_USING_INTERRUPTS */
+
+	/* Prevent the microkernel being woken up before there is something to do. */
+	psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+	eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+	/* Register the device with the power manager. */
+	eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
+										&SGXPrePowerState, &SGXPostPowerState,
+										&SGXPreClockSpeedChange, &SGXPostClockSpeedChange,
+										(IMG_HANDLE)psDeviceNode,
+										PVRSRV_DEV_POWER_STATE_OFF,
+										eDefaultPowerState);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: failed to register device with power manager"));
+		return eError;
+	}
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+	/* map the external system cache control registers into the SGX MMU */
+	psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
+	psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
+	eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
+		return eError;
+	}
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
+
+	/*
+		Initialise the Kernel CCB
+	*/
+	OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
+	OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
+	OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker));
+	PDUMPCOMMENT("Initialise Kernel CCB");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0, sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+	PDUMPCOMMENT("Initialise Kernel CCB Control");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0, sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+	PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+	return PVRSRV_OK;
+
+failed_init_dev_info:
+	return eError;
+}
+
+/*!
+*******************************************************************************
+
+ @Function	DevDeInitSGX
+
+ @Description
+
+ Reset and deinitialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
+{
+	PVRSRV_DEVICE_NODE			*psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+	PVRSRV_SGXDEV_INFO			*psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	PVRSRV_ERROR				eError;
+	IMG_UINT32					ui32Heap;
+	DEVICE_MEMORY_HEAP_INFO		*psDeviceMemoryHeap;
+	SGX_DEVICE_MAP				*psSGXDeviceMap;
+
+	if (!psDevInfo)
+	{
+		/* Can happen if DevInitSGX failed */
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
+		return PVRSRV_OK;
+	}
+
+#if defined(SUPPORT_HW_RECOVERY)
+	if (psDevInfo->hTimer)
+	{
+		eError = OSRemoveTimer(psDevInfo->hTimer);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to remove timer"));
+			return 	eError;
+		}
+		psDevInfo->hTimer = IMG_NULL;
+	}
+#endif /* SUPPORT_HW_RECOVERY */
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+	/* unmap the external system cache control registers  */
+	eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
+		return eError;
+	}
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
+
+	MMU_BIFResetPDFree(psDevInfo);
+
+	/*
+		DeinitDevInfo the DevInfo
+	*/
+	DeinitDevInfo(psDevInfo);
+
+	/* Destroy heaps. */
+	psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
+	for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
+	{
+		switch(psDeviceMemoryHeap[ui32Heap].DevMemHeapType)
+		{
+			case DEVICE_MEMORY_HEAP_KERNEL:
+			case DEVICE_MEMORY_HEAP_SHARED:
+			case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+			{
+				if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap != IMG_NULL)
+				{
+					BM_DestroyHeap(psDeviceMemoryHeap[ui32Heap].hDevMemHeap);
+				}
+				break;
+			}
+		}
+	}
+
+	/* Destroy the kernel context. */
+	eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX : Failed to destroy kernel context"));
+		return eError;
+	}
+
+	/* remove the device from the power manager */
+	eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
+	if (eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+
+	eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+									(IMG_VOID**)&psSGXDeviceMap);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to get device memory map!"));
+		return eError;
+	}
+
+	/* Only unmap the registers if they were mapped here */
+	if (!psSGXDeviceMap->pvRegsCpuVBase)
+	{
+		/* UnMap Regs */
+		if (psDevInfo->pvRegsBaseKM != IMG_NULL)
+		{
+			OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+							 psDevInfo->ui32RegSize,
+							 PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+							 IMG_NULL);
+		}
+	}
+
+#if defined(SGX_FEATURE_HOST_PORT)
+	if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+	{
+		/* unMap Host Port */
+		if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
+		{
+			OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+						   psDevInfo->ui32HPSize,
+						   PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+						   IMG_NULL);
+		}
+	}
+#endif /* #ifdef SGX_FEATURE_HOST_PORT */
+	
+	/* DeAllocate devinfo */
+	OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_SGXDEV_INFO),
+				psDevInfo,
+				0);
+
+	psDeviceNode->pvDevice = IMG_NULL;
+
+	if (psDeviceMemoryHeap != IMG_NULL)
+	{
+	/* Free the device memory heap info. */
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+				psDeviceMemoryHeap,
+				0);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXDumpDebugReg
+
+ @Description
+
+ Dump a single SGX debug register value
+
+ @Input psDevInfo - SGX device info
+ @Input ui32CoreNum - processor number
+ @Input pszName - string used for logging
+ @Input ui32RegAddr - SGX register offset
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO	*psDevInfo,
+								 IMG_UINT32			ui32CoreNum,
+								 IMG_CHAR			*pszName,
+								 IMG_UINT32			ui32RegAddr)
+{
+	IMG_UINT32	ui32RegVal;
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(ui32RegAddr, ui32CoreNum));
+	PVR_LOG(("(P%u) %s%08X", ui32CoreNum, pszName, ui32RegVal));
+}
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) || defined(FIX_HW_BRN_31620)
+static INLINE IMG_UINT32 GetDirListBaseReg(IMG_UINT32 ui32Index)
+{
+	if (ui32Index == 0)
+	{
+		return EUR_CR_BIF_DIR_LIST_BASE0;
+	}
+	else
+	{
+		return (EUR_CR_BIF_DIR_LIST_BASE1 + ((ui32Index - 1) * 0x4));
+	}
+}
+#endif
+
+/*!
+ * **************************************************************************
+ * @Function	RunSGXREGDebugScripts
+ * @Description	Runs the SGXREG debug scripts
+ *
+ * @Input	PVRSRV_SGXDEV_INFO
+ * @Output
+ * @Return	IMG_VOID
+ * **************************************************************************/
+
+IMG_VOID RunSGXREGDebugScripts (PVRSRV_SGXDEV_INFO	*psDevInfo)
+{
+	IMG_UINT32	ui32Core;
+	PVRSRV_ERROR		eError;
+
+	/* Run SGXREGDebug scripts */
+#if defined(SGX_FEATURE_MP)
+	PVR_LOG(("(HYD)"));
+	eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asSGXREGDebugCommandsMaster, SGX_MAX_PRINT_COMMANDS);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"RunSGXREGDebugScripts: SGXREGDebugCommandsMaster SGXRunScript failed (%d)", eError));
+	}
+#endif
+
+	/* Run on each core */
+	for (ui32Core = 0; ui32Core < SGX_FEATURE_MP_CORE_COUNT_3D; ui32Core++) 
+	{
+		PVR_LOG(("(P%u)",ui32Core));
+		eError = SGXRunScriptOnCore(psDevInfo, psDevInfo->sScripts.asSGXREGDebugCommandsSlave, SGX_MAX_PRINT_COMMANDS, ui32Core);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"RunSGXREGDebugScripts: SGXREGDebugCommandsSlave SGXRunScript failed (%d)", eError));
+		}
+	}
+	/* Scripts end */
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXDumpDebugInfo
+
+ @Description
+
+ Dump useful debugging info
+
+ @Input psDevInfo	 - SGX device info
+ @Input bDumpSGXRegs - Whether to dump SGX debug registers. Must not be done
+ 						when SGX is not powered.
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO	*psDevInfo,
+						   IMG_BOOL				bDumpSGXRegs)
+{
+	IMG_UINT32	ui32CoreNum;
+
+	PVR_LOG(("SGX debug (%s)", PVRVERSION_STRING));
+
+	if (bDumpSGXRegs)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Linear):   0x%p", psDevInfo->pvRegsBaseKM));
+		PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Physical): 0x" SYSPADDR_FMT, psDevInfo->sRegsPhysBase.uiAddr));
+
+		/* Run SGXREGDebug Scripts */
+		PVR_LOG(("Running SGXREG Debug Scripts:"));
+		RunSGXREGDebugScripts(psDevInfo);
+
+		PVR_LOG(("SGX Register Dump:"));
+		SGXDumpDebugReg(psDevInfo, 0, "EUR_CR_CORE_ID:          ", EUR_CR_CORE_ID);
+		SGXDumpDebugReg(psDevInfo, 0, "EUR_CR_CORE_REVISION:    ", EUR_CR_CORE_REVISION);
+		
+		for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
+		{
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS:     ", EUR_CR_EVENT_STATUS);
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS2:    ", EUR_CR_EVENT_STATUS2);
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_CTRL:         ", EUR_CR_BIF_CTRL);
+		#if defined(EUR_CR_BIF_BANK0)
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK0:        ", EUR_CR_BIF_BANK0);	
+		#endif
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_INT_STAT:     ", EUR_CR_BIF_INT_STAT);
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_FAULT:        ", EUR_CR_BIF_FAULT);
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_MEM_REQ_STAT: ", EUR_CR_BIF_MEM_REQ_STAT);
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL:       ", EUR_CR_CLKGATECTL);
+		#if defined(EUR_CR_PDS_PC_BASE)
+			SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_PDS_PC_BASE:      ", EUR_CR_PDS_PC_BASE);
+		#endif
+		}
+
+	#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && !defined(FIX_HW_BRN_31620)
+		{
+			IMG_UINT32 ui32RegVal;
+			IMG_UINT32 ui32PDDevPAddr;
+	
+			/*
+				If there was a SGX pagefault check the page table too see if the
+				host thinks the fault is correct
+			*/
+			ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+			#if defined(EUR_CR_BIF_INT_STAT_PF_N_RW_MASK)
+			if (ui32RegVal & EUR_CR_BIF_INT_STAT_PF_N_RW_MASK)
+			#else
+			if (ui32RegVal & EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK)	
+			#endif
+			{
+				ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+				ui32RegVal &= EUR_CR_BIF_FAULT_ADDR_MASK;
+				ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0);
+				ui32PDDevPAddr &= EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK;
+				MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32RegVal);
+			}
+		}
+	#else
+		{
+			IMG_UINT32 ui32FaultAddress;
+			IMG_UINT32 ui32Bank0;
+			IMG_UINT32 ui32DirListIndex;
+			IMG_UINT32 ui32PDDevPAddr;
+			IMG_UINT32 ui32RegVal;
+
+#if defined(SGX_FEATURE_MP)
+			ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_INT_STAT);
+#if defined(EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK)
+			if( ui32RegVal & EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK)
+#else
+			if( ui32RegVal & EUR_CR_BIF_INT_STAT_PF_N_RW_MASK)
+#endif
+			{
+				ui32FaultAddress = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_FAULT);
+				if(ui32FaultAddress)
+				{
+					ui32Bank0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0);
+		
+					/* Check the EDM's's memory context */
+					ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_EDM_MASK) >> EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT;
+					ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+													GetDirListBaseReg(ui32DirListIndex));
+					PVR_LOG(("Checking EDM memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+					MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+			
+					/* Check the TA's memory context */
+					ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_TA_MASK) >> EUR_CR_BIF_BANK0_INDEX_TA_SHIFT;
+					ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+													GetDirListBaseReg(ui32DirListIndex));
+					PVR_LOG(("Checking TA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+					MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+		
+					/* Check the 3D's memory context */
+					ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_3D_MASK) >> EUR_CR_BIF_BANK0_INDEX_3D_SHIFT;
+					ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+													GetDirListBaseReg(ui32DirListIndex));
+					PVR_LOG(("Checking 3D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+					MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+			
+			#if defined(EUR_CR_BIF_BANK0_INDEX_2D_MASK)
+					/* Check the 2D's memory context */
+					ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_2D_MASK) >> EUR_CR_BIF_BANK0_INDEX_2D_SHIFT;
+					ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+													GetDirListBaseReg(ui32DirListIndex));
+					PVR_LOG(("Checking 2D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+					MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+			#endif
+			
+			#if defined(EUR_CR_BIF_BANK0_INDEX_PTLA_MASK)
+					/* Check the 2D's memory context */
+					ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_PTLA_MASK) >> EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT;
+					ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+													GetDirListBaseReg(ui32DirListIndex));
+					PVR_LOG(("Checking PTLA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+					MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+			#endif
+	
+			#if defined(EUR_CR_BIF_BANK0_INDEX_HOST_MASK)
+					/* Check the Host's memory context */
+					ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_HOST_MASK) >> EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT;
+					ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+													GetDirListBaseReg(ui32DirListIndex));
+					PVR_LOG(("Checking Host memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+					MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+					
+			#endif
+				}
+			}
+#endif
+			for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
+			{
+
+				ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BIF_INT_STAT, ui32CoreNum));
+	#if defined(EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK)
+				if( ui32RegVal & EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK)
+	#else
+				if( ui32RegVal & EUR_CR_BIF_INT_STAT_PF_N_RW_MASK)
+	#endif
+				{
+					ui32FaultAddress = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BIF_FAULT, ui32CoreNum));
+					ui32FaultAddress &= EUR_CR_BIF_FAULT_ADDR_MASK;
+					if(ui32FaultAddress)
+					{
+						ui32Bank0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0);
+			
+						/* Check the EDM's's memory context */
+						ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_EDM_MASK) >> EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT;
+						ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+														GetDirListBaseReg(ui32DirListIndex));
+						PVR_LOG(("Checking EDM memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+						MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+				
+						/* Check the TA's memory context */
+						ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_TA_MASK) >> EUR_CR_BIF_BANK0_INDEX_TA_SHIFT;
+						ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+														GetDirListBaseReg(ui32DirListIndex));
+						PVR_LOG(("Checking TA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+						MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+			
+						/* Check the 3D's memory context */
+						ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_3D_MASK) >> EUR_CR_BIF_BANK0_INDEX_3D_SHIFT;
+						ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+														GetDirListBaseReg(ui32DirListIndex));
+						PVR_LOG(("Checking 3D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+						MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+				
+				#if defined(EUR_CR_BIF_BANK0_INDEX_2D_MASK)
+						/* Check the 2D's memory context */
+						ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_2D_MASK) >> EUR_CR_BIF_BANK0_INDEX_2D_SHIFT;
+						ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+														GetDirListBaseReg(ui32DirListIndex));
+						PVR_LOG(("Checking 2D memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+						MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+				#endif		
+					
+				#if defined(EUR_CR_BIF_BANK0_INDEX_PTLA_MASK)
+						/* Check the 2D's memory context */
+						ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_PTLA_MASK) >> EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT;
+						ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+														GetDirListBaseReg(ui32DirListIndex));
+						PVR_LOG(("Checking PTLA memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+						MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+				#endif	
+		
+				#if defined(EUR_CR_BIF_BANK0_INDEX_HOST_MASK)
+						/* Check the Host's memory context */
+						ui32DirListIndex = (ui32Bank0 & EUR_CR_BIF_BANK0_INDEX_HOST_MASK) >> EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT;
+						ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+													GetDirListBaseReg(ui32DirListIndex));
+						PVR_LOG(("Checking Host memory context (index = %d, PD = 0x%08x)", ui32DirListIndex, ui32PDDevPAddr));
+						MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32FaultAddress);
+						
+				#endif
+					}
+				}
+			}
+		}
+	#endif
+	}
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	/*
+		Dump out the outstanding queue items.
+	*/
+	QueueDumpDebugInfo();
+#endif
+
+	{
+		/*
+			Dump out the Host control.
+		*/
+		SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+		IMG_UINT32			*pui32HostCtlBuffer = (IMG_UINT32 *)psSGXHostCtl;
+		IMG_UINT32			ui32LoopCounter;
+		
+		/* Report which defines are enabled that affect the HostCTL structure being dumped-out here */
+		{
+			IMG_UINT32 ui32CtlFlags = 0;
+			#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
+			ui32CtlFlags = ui32CtlFlags | 0x0001;
+			#endif
+			#if defined(FIX_HW_BRN_28889)
+			ui32CtlFlags = ui32CtlFlags | 0x0002;
+			#endif
+			#if defined(SUPPORT_HW_RECOVERY)
+			ui32CtlFlags = ui32CtlFlags | 0x0004;
+			#endif
+			#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+			ui32CtlFlags = ui32CtlFlags | 0x0008;
+			#endif
+			PVR_LOG((" Host Ctl flags= %08x", ui32CtlFlags));
+		}
+		
+		if (psSGXHostCtl->ui32AssertFail != 0)
+		{
+			PVR_LOG(("SGX Microkernel assert fail: 0x%08X", psSGXHostCtl->ui32AssertFail));
+			psSGXHostCtl->ui32AssertFail = 0;
+		}
+
+		PVR_LOG(("SGX Host control:"));
+
+		for (ui32LoopCounter = 0;
+			 ui32LoopCounter < sizeof(*psDevInfo->psSGXHostCtl) / sizeof(*pui32HostCtlBuffer);
+			 ui32LoopCounter += 4)
+		{
+			PVR_LOG(("\t(HC-%" SIZE_T_FMT_LEN "X) 0x%08X 0x%08X 0x%08X 0x%08X", 
+                    ui32LoopCounter * sizeof(*pui32HostCtlBuffer),
+					pui32HostCtlBuffer[ui32LoopCounter + 0], pui32HostCtlBuffer[ui32LoopCounter + 1],
+					pui32HostCtlBuffer[ui32LoopCounter + 2], pui32HostCtlBuffer[ui32LoopCounter + 3]));
+		}
+	}
+
+	{
+		/*
+			Dump out the TA/3D control.
+		*/
+		IMG_UINT32	*pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
+		IMG_UINT32	ui32LoopCounter;
+
+		PVR_LOG(("SGX TA/3D control:"));
+
+		for (ui32LoopCounter = 0;
+			 ui32LoopCounter < psDevInfo->psKernelSGXTA3DCtlMemInfo->uAllocSize / sizeof(*pui32TA3DCtlBuffer);
+			 ui32LoopCounter += 4)
+		{
+			PVR_LOG(("\t(T3C-%" SIZE_T_FMT_LEN "X) 0x%08X 0x%08X 0x%08X 0x%08X", 
+                    ui32LoopCounter * sizeof(*pui32TA3DCtlBuffer),
+					pui32TA3DCtlBuffer[ui32LoopCounter + 0], pui32TA3DCtlBuffer[ui32LoopCounter + 1],
+					pui32TA3DCtlBuffer[ui32LoopCounter + 2], pui32TA3DCtlBuffer[ui32LoopCounter + 3]));
+		}
+	}
+
+	#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+	{
+		IMG_UINT32	*pui32MKTraceBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+		IMG_UINT32	ui32LastStatusCode, ui32WriteOffset;
+
+		ui32LastStatusCode = *pui32MKTraceBuffer;
+		pui32MKTraceBuffer++;
+		ui32WriteOffset = *pui32MKTraceBuffer;
+		pui32MKTraceBuffer++;
+
+		PVR_LOG(("Last SGX microkernel status code: %08X %s",
+				 ui32LastStatusCode, SGXUKernelStatusString(ui32LastStatusCode)));
+
+		#if defined(PVRSRV_DUMP_MK_TRACE)
+		/*
+			Dump the raw microkernel trace buffer to the log.
+		*/
+		{
+			IMG_UINT32	ui32LoopCounter;
+
+			for (ui32LoopCounter = 0;
+				 ui32LoopCounter < SGXMK_TRACE_BUFFER_SIZE;
+				 ui32LoopCounter++)
+			{
+				IMG_UINT32	*pui32BufPtr;
+				pui32BufPtr = pui32MKTraceBuffer +
+								(((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
+				PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X %s", ui32LoopCounter,
+						 pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0],
+						 SGXUKernelStatusString(pui32BufPtr[0])));
+			}
+		}
+		#endif /* PVRSRV_DUMP_MK_TRACE */
+	}
+	#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
+
+	{
+		/*
+			Dump out the kernel CCB.
+		*/
+		PVR_LOG(("SGX Kernel CCB WO:0x%X RO:0x%X",
+				psDevInfo->psKernelCCBCtl->ui32WriteOffset,
+				psDevInfo->psKernelCCBCtl->ui32ReadOffset));
+
+		#if defined(PVRSRV_DUMP_KERNEL_CCB)
+		{
+			IMG_UINT32	ui32LoopCounter;
+
+			for (ui32LoopCounter = 0;
+				 ui32LoopCounter < sizeof(psDevInfo->psKernelCCB->asCommands) /
+				 					sizeof(psDevInfo->psKernelCCB->asCommands[0]);
+				 ui32LoopCounter++)
+			{
+				SGXMKIF_COMMAND	*psCommand = &psDevInfo->psKernelCCB->asCommands[ui32LoopCounter];
+
+				PVR_LOG(("\t(KCCB-%X) %08X %08X - %08X %08X %08X %08X", ui32LoopCounter,
+						psCommand->ui32ServiceAddress, psCommand->ui32CacheControl,
+						psCommand->ui32Data[0], psCommand->ui32Data[1],
+						psCommand->ui32Data[2], psCommand->ui32Data[3]));
+			}
+		}
+		#endif /* PVRSRV_DUMP_KERNEL_CCB */
+	}
+	#if defined (TTRACE)
+	PVRSRVDumpTimeTraceBuffers();
+	#endif
+
+	#if defined (SUPPORT_FORCE_SYNC_DUMP)
+	PVRSRVDumpSyncs(IMG_FALSE);
+	#else
+	PVRSRVDumpSyncs(IMG_TRUE);
+	#endif
+	
+
+#if defined (MEM_TRACK_INFO_DEBUG)
+	{
+		IMG_UINT32 ui32FaultAddress = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BIF_FAULT, 0));
+		PVRSRVPrintMemTrackInfo(ui32FaultAddress);
+	}
+#endif
+
+
+#if defined(PVRSRV_DEBUG_CCB_MAX)
+	PVRSRVDebugPrintfDumpCCB();
+#endif
+}
+
+
+#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+/*!
+*******************************************************************************
+
+ @Function	HWRecoveryResetSGX
+
+ @Description
+
+ Resets SGX
+
+ Note: may be called from an ISR so should not call pdump.
+
+ @Input psDevInfo - dev info
+
+ @Input ui32Component - core component to reset
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+static
+IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
+							 IMG_UINT32 		ui32Component,
+							 IMG_UINT32			ui32CallerID)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+	
+#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT)	
+	static IMG_UINT32	ui32Clockinus = 0;
+	static IMG_UINT32	ui32HWRecoveryCount=0;
+	IMG_UINT32			ui32TempClockinus=0;
+#endif	
+	
+	PVR_UNREFERENCED_PARAMETER(ui32Component);
+
+	/*
+		Ensure that hardware recovery is serialised with any power transitions.
+	*/
+	eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+	if(eError != PVRSRV_OK)
+	{
+		/*
+			Unable to obtain lock because there is already a power transition
+			in progress.
+		*/
+		PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
+		return;
+	}
+
+	psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+
+	PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
+
+#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT)	
+/*
+ * 		The following defines are system specific and should be defined in
+ * 		the corresponding sysconfig.h file. The values indicated are examples only.
+		SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD		5000000 //(5 Seconds)
+		SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT			5
+		*/
+		ui32TempClockinus = OSClockus();
+	if((ui32TempClockinus-ui32Clockinus) < SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD){
+		ui32HWRecoveryCount++;
+		if(SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT <= ui32HWRecoveryCount){
+			OSPanic();	
+		}
+	}else{
+		ui32Clockinus = ui32TempClockinus;
+		SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+		ui32HWRecoveryCount = 0;
+	}
+#else	
+	SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+#endif
+	
+	/* Suspend pdumping. */
+	PDUMPSUSPEND();
+
+	/* Reset and re-initialise SGX. */
+	eError = SGXInitialise(psDevInfo, IMG_TRUE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
+	}
+
+	/* Resume pdumping. */
+	PDUMPRESUME();
+
+	PVRSRVPowerUnlock(ui32CallerID);
+
+	/* Send a dummy kick so that we start processing again */
+	SGXScheduleProcessQueuesKM(psDeviceNode);
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	/* Flush any old commands from the queues. */
+	PVRSRVProcessQueues(IMG_TRUE);
+#endif
+}
+#endif /* #if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY) */
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+/*!
+******************************************************************************
+
+ @Function	SGXOSTimer
+
+ @Description
+
+ Timer function for SGX
+
+ @Input pvData - private data
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+IMG_VOID SGXOSTimer(IMG_VOID *pvData)
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+	PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	static IMG_UINT32	ui32EDMTasks = 0;
+	static IMG_UINT32	ui32LockupCounter = 0; /* To prevent false positives */
+	static IMG_UINT32	ui32OpenCLDelayCounter = 0;
+	static IMG_UINT32	ui32NumResets = 0;
+#if defined(FIX_HW_BRN_31093)
+	static IMG_BOOL		bBRN31093Inval = IMG_FALSE;
+#endif
+	IMG_UINT32		ui32CurrentEDMTasks;
+	IMG_UINT32		ui32CurrentOpenCLDelayCounter=0;
+	IMG_BOOL		bLockup = IMG_FALSE;
+	IMG_BOOL		bPoweredDown;
+
+	/* increment a timestamp */
+	psDevInfo->ui32TimeStamp++;
+
+#if defined(NO_HARDWARE)
+	bPoweredDown = IMG_TRUE;
+#else
+	bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE;
+#endif /* NO_HARDWARE */
+
+	/*
+	 * Check whether EDM timer tasks are getting scheduled. If not, assume
+	 * that SGX has locked up and reset the chip.
+	 */
+
+	/* Check whether the timer should be running */
+	if (bPoweredDown)
+	{
+		ui32LockupCounter = 0;
+	#if defined(FIX_HW_BRN_31093)
+		bBRN31093Inval = IMG_FALSE;
+	#endif
+	}
+	else
+	{
+		/* The PDS timer should be running. */
+		ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
+		if (psDevInfo->ui32EDMTaskReg1 != 0)
+		{
+			ui32CurrentEDMTasks ^= OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg1);
+		}
+		if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
+			(psDevInfo->ui32NumResets == ui32NumResets))
+		{
+			ui32LockupCounter++;
+			if (ui32LockupCounter == 3)
+			{
+				ui32LockupCounter = 0;
+				ui32CurrentOpenCLDelayCounter = (psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount;
+				if(0 != ui32CurrentOpenCLDelayCounter)
+				{
+					if(ui32OpenCLDelayCounter != ui32CurrentOpenCLDelayCounter){
+						ui32OpenCLDelayCounter = ui32CurrentOpenCLDelayCounter;
+					}else{
+						ui32OpenCLDelayCounter -= 1;
+						(psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = ui32OpenCLDelayCounter;
+					}
+					goto SGX_NoUKernel_LockUp;
+				}
+
+
+	#if defined(FIX_HW_BRN_31093)
+				if (bBRN31093Inval == IMG_FALSE)
+				{
+					/* It could be a BIF hang so do a INVAL_PTE */
+		#if defined(FIX_HW_BRN_29997)
+					IMG_UINT32	ui32BIFCtrl;
+				/* Pause the BIF before issuing the invalidate */
+					ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+					OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK);
+					/* delay for 200 clocks */
+					SGXWaitClocks(psDevInfo, 200);
+		#endif
+					/* Flag that we have attempt to un-block the BIF */
+					bBRN31093Inval = IMG_TRUE;
+					
+					OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK);
+					/* delay for 200 clocks */
+					SGXWaitClocks(psDevInfo, 200);
+						
+		#if defined(FIX_HW_BRN_29997)	
+					/* un-pause the BIF by restoring the BIF_CTRL */	
+					OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+		#endif
+				}
+				else
+	#endif
+				{
+					PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
+
+					bLockup = IMG_TRUE;
+					(psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = 0;
+				}
+			}
+		}
+		else
+		{
+	#if defined(FIX_HW_BRN_31093)
+			bBRN31093Inval = IMG_FALSE;
+	#endif
+			ui32LockupCounter = 0;
+			ui32EDMTasks = ui32CurrentEDMTasks;
+			ui32NumResets = psDevInfo->ui32NumResets;
+		}
+	}
+SGX_NoUKernel_LockUp:
+
+	if (bLockup)
+	{
+		SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+		/* increment the counter so we know the host detected the lockup */
+		psSGXHostCtl->ui32HostDetectedLockups ++;
+
+		/* Reset the chip and process the queues. */
+		HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+	}
+}
+#endif /* defined(SUPPORT_HW_RECOVERY) */
+
+
+
+#if defined(SYS_USING_INTERRUPTS)
+
+/*
+	SGX ISR Handler
+*/
+IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
+{
+	IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+
+	/* Real Hardware */
+	{
+		IMG_UINT32 ui32EventStatus, ui32EventEnable;
+		IMG_UINT32 ui32EventClear = 0;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+		IMG_UINT32 ui32EventStatus2, ui32EventEnable2;
+#endif		
+		IMG_UINT32 ui32EventClear2 = 0;
+		PVRSRV_DEVICE_NODE *psDeviceNode;
+		PVRSRV_SGXDEV_INFO *psDevInfo;
+
+		/* check for null pointers */
+		if(pvData == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
+			return bInterruptProcessed;
+		}
+
+		psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+		psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+		ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+		ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
+
+		/* test only the unmasked bits */
+		ui32EventStatus &= ui32EventEnable;
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+		ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+		ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2);
+
+		/* test only the unmasked bits */
+		ui32EventStatus2 &= ui32EventEnable2;
+#endif /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */
+
+		/* Thought: is it better to insist that the bit assignment in
+		   the "clear" register(s) matches that of the "status" register(s)?
+		   It would greatly simplify this LISR */
+
+		if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
+		{
+			ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+		}
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+		if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK)
+		{
+			ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK;
+		}
+
+		if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK)
+		{
+			ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK;
+		}
+#endif /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */
+
+		if (ui32EventClear || ui32EventClear2)
+		{
+			bInterruptProcessed = IMG_TRUE;
+
+			/* Clear master interrupt bit */
+			ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+			/* clear the events */
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2);
+
+			/*
+				Sample the current count from the uKernel _after_ we've cleared the
+				interrupt.
+			*/
+			g_ui32HostIRQCountSample = psDevInfo->psSGXHostCtl->ui32InterruptCount;
+		}
+	}
+
+	return bInterruptProcessed;
+}
+
+/*
+	SGX Systrace Handler
+*/
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+static IMG_VOID SGXSystraceHandler(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+	IMG_UINT32 ui32SgxClockSpeed, ui32DataCount, ui32HostTimestamp;
+
+	/* NOTE: Not thread safe. MISR should only run in one thread */
+	static PVRSRV_SGX_HWPERF_CB_ENTRY asSGXHWPerf[16];
+
+	if(SystraceIsCapturingHWData() && psDevInfo->bSystraceInitialised)
+	{
+		SGXReadHWPerfCBKM((IMG_HANDLE) psDeviceNode, 
+						16,
+						asSGXHWPerf,
+						(IMG_UINT32 *)&ui32DataCount,
+						(IMG_UINT32 *)&ui32SgxClockSpeed,
+						(IMG_UINT32 *)&ui32HostTimestamp);
+
+		SystraceHWPerfPackets(psDevInfo, asSGXHWPerf, ui32DataCount, ui32SgxClockSpeed);
+	} 
+	else if(SystraceIsCapturingHWData() && !psDevInfo->bSystraceInitialised)
+	{
+		SGX_MISC_INFO sSGXMiscInfo;
+
+		if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SYSTRACE_DATA),
+					  (IMG_VOID **)&psDevInfo->psSystraceData, 0,
+					  "Systrace data storage") != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGXSystraceHandler: Failed to allocate systrace data"));
+			return;
+		}
+
+		OSMemSet(psDevInfo->psSystraceData, 0, sizeof(PVRSRV_SYSTRACE_DATA));
+
+		/* Prepare the SGXMiscInfo request in order to stop recording data*/
+		sSGXMiscInfo.eRequest = SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS;
+		sSGXMiscInfo.uData.sSetHWPerfStatus.ui32NewHWPerfStatus = PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON | PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON;
+
+		/* Call into SGX DDK KM Services*/
+		SGXGetMiscInfoKM(psDevInfo, &sSGXMiscInfo, psDeviceNode, NULL);
+
+		psDevInfo->bSystraceInitialised = IMG_TRUE;
+
+		/* Initialize the first context to be 1 (0 is idle)*/
+		psDevInfo->psSystraceData->ui32CurrentCtxID = 1;
+
+		/* Initialize current GPU ticks and Host Time */
+		SystraceInitializeTimeCorr(psDevInfo);
+	}
+	else if(psDevInfo->bSystraceInitialised)
+	{
+		SGX_MISC_INFO sSGXMiscInfo;
+
+		/* Prepare the SGXMiscInfo request in order to stop recording data*/
+		sSGXMiscInfo.eRequest = SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS;
+		sSGXMiscInfo.uData.sSetHWPerfStatus.ui32NewHWPerfStatus = 0;
+
+		/* Call into SGX DDK KM Services*/
+		SGXGetMiscInfoKM(psDevInfo, &sSGXMiscInfo, psDeviceNode, NULL);
+
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SYSTRACE_DATA), psDevInfo->psSystraceData, NULL);
+		psDevInfo->bSystraceInitialised = IMG_FALSE;
+	}
+}
+#endif
+
+/*
+	SGX MISR Handler
+*/
+static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+	if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) != 0UL) &&
+		((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) == 0UL))
+	{
+		HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+	}
+
+	if (psDeviceNode->bReProcessDeviceCommandComplete)
+	{
+		SGXScheduleProcessQueuesKM(psDeviceNode);
+	}
+
+	SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+	
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	SGXSystraceHandler(psDeviceNode);
+#endif
+	
+}
+#endif /* #if defined (SYS_USING_INTERRUPTS) */
+
+#if defined(SUPPORT_MEMORY_TILING)
+
+IMG_INTERNAL
+PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+									 PVRSRV_KERNEL_MEM_INFO	*psMemInfo,
+									 IMG_UINT32 ui32XTileStride,
+									 IMG_UINT32 *pui32RangeIndex)
+{
+	return SGX_AllocMemTilingRangeInt(psDeviceNode->pvDevice,
+		psMemInfo->sDevVAddr.uiAddr,
+		psMemInfo->sDevVAddr.uiAddr + ((IMG_UINT32) psMemInfo->uAllocSize) + SGX_MMU_PAGE_SIZE - 1,
+		ui32XTileStride,
+		pui32RangeIndex);
+}
+
+IMG_INTERNAL
+PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+										IMG_UINT32 ui32RangeIndex)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+	IMG_UINT32 ui32Offset;
+	IMG_UINT32 ui32Val;
+
+	if(ui32RangeIndex >= 10)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: invalid Range index "));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	/* clear the usage bit */
+	psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex);
+
+	/* disable the range */
+	ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2);
+	ui32Val = 0;
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+	PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+	return PVRSRV_OK;
+}
+
+#endif /* defined(SUPPORT_MEMORY_TILING) */
+
+
+static IMG_VOID SGXCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+	#if defined(SGX_FEATURE_MP)
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+	#else
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	#endif /* SGX_FEATURE_MP */
+}
+
+/*!
+*******************************************************************************
+
+ @Function	SGXRegisterDevice
+
+ @Description
+
+ Registers the device with the system
+
+ @Input: 	psDeviceNode - device node
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	DEVICE_MEMORY_INFO *psDevMemoryInfo;
+	DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+	/* setup details that never change */
+	psDeviceNode->sDevId.eDeviceType		= DEV_DEVICE_TYPE;
+	psDeviceNode->sDevId.eDeviceClass		= DEV_DEVICE_CLASS;
+#if defined(PDUMP)
+	{
+		/* memory space names are set up in system code */
+		SGX_DEVICE_MAP *psSGXDeviceMemMap;
+		SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+							  (IMG_VOID**)&psSGXDeviceMemMap);
+
+		psDeviceNode->sDevId.pszPDumpDevName = psSGXDeviceMemMap->pszPDumpDevName;
+		PVR_ASSERT(psDeviceNode->sDevId.pszPDumpDevName != IMG_NULL);
+	}
+	
+	psDeviceNode->sDevId.pszPDumpRegName	= SGX_PDUMPREG_NAME;
+#endif /* PDUMP */
+
+	psDeviceNode->pfnInitDevice		= &DevInitSGXPart1;
+	psDeviceNode->pfnDeInitDevice	= &DevDeInitSGX;
+
+	psDeviceNode->pfnInitDeviceCompatCheck	= &SGXDevInitCompatCheck;
+#if defined(PDUMP)
+	psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump;
+	psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID;
+#endif
+	/*
+		MMU callbacks
+	*/
+	psDeviceNode->pfnMMUInitialise = &MMU_Initialise;
+	psDeviceNode->pfnMMUFinalise = &MMU_Finalise;
+	psDeviceNode->pfnMMUInsertHeap = &MMU_InsertHeap;
+	psDeviceNode->pfnMMUCreate = &MMU_Create;
+	psDeviceNode->pfnMMUDelete = &MMU_Delete;
+	psDeviceNode->pfnMMUAlloc = &MMU_Alloc;
+	psDeviceNode->pfnMMUFree = &MMU_Free;
+	psDeviceNode->pfnMMUMapPages = &MMU_MapPages;
+	psDeviceNode->pfnMMUMapShadow = &MMU_MapShadow;
+	psDeviceNode->pfnMMUUnmapPages = &MMU_UnmapPages;
+	psDeviceNode->pfnMMUMapScatter = &MMU_MapScatter;
+	psDeviceNode->pfnMMUGetPhysPageAddr = &MMU_GetPhysPageAddr;
+	psDeviceNode->pfnMMUGetPDDevPAddr = &MMU_GetPDDevPAddr;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	psDeviceNode->pfnMMUIsHeapShared = &MMU_IsHeapShared;
+#endif
+#if defined(FIX_HW_BRN_31620)
+	psDeviceNode->pfnMMUGetCacheFlushRange = &MMU_GetCacheFlushRange;
+	psDeviceNode->pfnMMUGetPDPhysAddr = &MMU_GetPDPhysAddr;
+#else
+	psDeviceNode->pfnMMUGetCacheFlushRange = IMG_NULL;
+	psDeviceNode->pfnMMUGetPDPhysAddr = IMG_NULL;
+#endif
+	psDeviceNode->pfnMMUMapPagesSparse = &MMU_MapPagesSparse;
+	psDeviceNode->pfnMMUMapShadowSparse = &MMU_MapShadowSparse;
+
+#if defined (SYS_USING_INTERRUPTS)
+	/*
+		SGX ISR handler
+	*/
+	psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+	psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+	psDeviceNode->pfnAllocMemTilingRange = SGX_AllocMemTilingRange;
+	psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange;
+#endif
+
+	/*
+		SGX command complete handler
+	*/
+	psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete;
+
+	psDeviceNode->pfnCacheInvalidate = SGXCacheInvalidate;
+
+	/*
+		and setup the device's memory map:
+	*/
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+	/* size of address space */
+	psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
+
+	/* flags, backing store details to be specified by system */
+	psDevMemoryInfo->ui32Flags = 0;
+
+	/* device memory heap info about each heap in a device address space */
+	if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+					 sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+					 (IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
+					 "Array of Device Memory Heap Info") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
+		return (PVRSRV_ERROR_OUT_OF_MEMORY);
+	}
+	OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0, sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID);
+
+	psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+	/*
+		setup heaps
+		Note: backing store to be setup by system (defaults to UMA)
+	*/
+
+	/************* general ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "General";
+	psDeviceMemoryHeap->pszBSName = "General BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) && !defined(SGX5300)
+	/* specify the mapping heap ID for this device */
+	psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+#endif
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+#if defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION)
+   /************* Texture Heap ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TEXTURE_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TEXTURE_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_TEXTURE_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+	                                | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+	                                | PVRSRV_HAP_SINGLE_PROCESS;
+ 
+	psDeviceMemoryHeap->pszName = "Texture";
+	psDeviceMemoryHeap->pszBSName = "Texture BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	/* The mapping heap ID should be texture heap for SGX5300 */
+#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) && defined(SGX5300)
+	/* specify the mapping heap ID for this device */
+	psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+#endif 
+	psDeviceMemoryHeap++;/* advance to the next heap */
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+	/************* VPB tiling ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VPB_TILED_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VPB_TILED_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_VPB_TILED_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "VPB Tiled";
+	psDeviceMemoryHeap->pszBSName = "VPB Tiled BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap->ui32XTileStride = SGX_VPB_TILED_HEAP_STRIDE;
+	PVR_DPF((PVR_DBG_WARNING, "VPB tiling heap tiling stride = 0x%x", psDeviceMemoryHeap->ui32XTileStride));
+	psDeviceMemoryHeap++;/* advance to the next heap */
+#endif
+
+	/************* TA data ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "TA Data";
+	psDeviceMemoryHeap->pszBSName = "TA Data BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* kernel code ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+															| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+															| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "Kernel Code";
+	psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* Kernel Video Data ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "KernelData";
+	psDeviceMemoryHeap->pszBSName = "KernelData BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* PixelShaderUSSE ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
+	/*
+		The actual size of the pixel and vertex shader heap must be such that all
+		addresses are within range of the one of the USSE code base registers, but
+		the addressable range is hardware-dependent.
+		SGX_PIXELSHADER_HEAP_SIZE is defined to be the maximum possible size
+		to ensure that the heap layout is consistent across all SGXs.
+	 */
+	psDeviceMemoryHeap->ui32HeapSize = ((10 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+	PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_PIXELSHADER_HEAP_SIZE);
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
+	psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* VertexShaderUSSE ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
+	/* See comment above with PixelShaderUSSE ui32HeapSize */
+	psDeviceMemoryHeap->ui32HeapSize = ((4 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+	PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_VERTEXSHADER_HEAP_SIZE);
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
+	psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* PDS Pixel Code/Data ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
+	psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* PDS Vertex Code/Data ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+																| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+																| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
+	psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* CacheCoherent ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "CacheCoherent";
+	psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	/* set the sync heap id */
+	psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+	/************* Shared 3D Parameters ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SHARED_3DPARAMETERS_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SHARED_3DPARAMETERS_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_SHARED_3DPARAMETERS_HEAP_SIZE;
+	psDeviceMemoryHeap->pszName = "Shared 3DParameters";
+	psDeviceMemoryHeap->pszBSName = "Shared 3DParameters BS";
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+													| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+													| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+	/************* Percontext 3D Parameters ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE;
+	psDeviceMemoryHeap->pszName = "Percontext 3DParameters";
+	psDeviceMemoryHeap->pszBSName = "Percontext 3DParameters BS";
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+															| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+															| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+	/************* General Mapping ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_MULTI_PROCESS;
+	psDeviceMemoryHeap->pszName = "GeneralMapping";
+	psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
+	#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
+	/*
+		if((2D hardware is enabled)
+		&& (multi-mem contexts enabled)
+		&& (BRN23410 is present))
+		 	- then don't make the heap per-context otherwise
+		 	the TA and 2D requestors must always be aligned to
+		 	the same address space which could affect performance
+	*/
+		psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+	#else /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */
+		psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+	#endif /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */
+
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	/* specify the mapping heap ID for this device */
+	psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+	psDeviceMemoryHeap++;/* advance to the next heap */
+#endif /* #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) */
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+	/************* 2D HW Heap ***************/
+	psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
+	psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
+	psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
+	psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+														| PVRSRV_MEM_RAM_BACKED_ALLOCATION
+														| PVRSRV_HAP_SINGLE_PROCESS;
+	psDeviceMemoryHeap->pszName = "2D";
+	psDeviceMemoryHeap->pszBSName = "2D BS";
+	psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+	/* set the default (4k). System can override these as required */
+	psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+	psDeviceMemoryHeap++;/* advance to the next heap */
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
+
+
+	/* set the heap count */
+	psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+
+	return PVRSRV_OK;
+}
+
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)(psDeviceNode->pvDevice);
+	psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+	PVR_DPF((PVR_DBG_MESSAGE, "Reset pdump CCB write offset."));
+	
+	return PVRSRV_OK;
+}
+#endif /* PDUMP */
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXGetClientInfoKM
+
+ @Description	Gets the client information
+
+ @Input hDevCookie
+
+ @Output psClientInfo
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE					hDevCookie,
+								SGX_CLIENT_INFO*		psClientInfo)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+	/*
+		If this is the first client to connect to SGX perform initialisation
+	*/
+	psDevInfo->ui32ClientRefCount++;
+
+	/*
+		Copy information to the client info.
+	*/
+	psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+	/*
+		Copy requested information.
+	*/
+	OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
+
+	/* just return OK */
+	return PVRSRV_OK;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXPanic
+
+ @Description
+
+ Called when an unrecoverable situation is detected. Dumps SGX debug
+ information and tells the OS to panic.
+
+ @Input psDevInfo - SGX device info
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO	*psDevInfo)
+{
+	PVR_LOG(("SGX panic"));
+	SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+	OSPanic();
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXDevInitCompatCheck
+
+ @Description
+
+ Check compatibility of host driver and microkernel (DDK and build options)
+ for SGX devices at services/device initialisation
+
+ @Input psDeviceNode - device node
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR	eError;
+	PVRSRV_SGXDEV_INFO 				*psDevInfo;
+	IMG_UINT32 			ui32BuildOptions, ui32BuildOptionsMismatch;
+#if !defined(NO_HARDWARE)
+	PPVRSRV_KERNEL_MEM_INFO			psMemInfo;
+	PVRSRV_SGX_MISCINFO_INFO		*psSGXMiscInfoInt; 	/*!< internal misc info for ukernel */
+	PVRSRV_SGX_MISCINFO_FEATURES	*psSGXFeatures;
+	SGX_MISCINFO_STRUCT_SIZES		*psSGXStructSizes;	/*!< microkernel structure sizes */
+	IMG_BOOL						bStructSizesFailed;
+
+	/* Exceptions list for core rev check, format is pairs of (hw rev, sw rev) */
+	IMG_BOOL	bCheckCoreRev;
+	const IMG_UINT32 aui32CoreRevExceptions[] =
+	{
+		0x10100, 0x10101
+	};
+	const IMG_UINT32	ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32));
+	IMG_UINT	i;
+#endif
+
+	/* Ensure it's a SGX device */
+	if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+	{
+		PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto chk_exit;
+	}
+
+	psDevInfo = psDeviceNode->pvDevice;
+
+	/*
+	 *  1. Check kernel-side and client-side build options
+	 *  2. Check ukernel build options against kernel-side build options
+	 */
+
+	/*
+	 * Check KM build options against client-side host driver
+	 */
+
+	ui32BuildOptions = (SGX_BUILD_OPTIONS);
+	if (ui32BuildOptions != psDevInfo->ui32ClientBuildOptions)
+	{
+		ui32BuildOptionsMismatch = ui32BuildOptions ^ psDevInfo->ui32ClientBuildOptions;
+		if ( (psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options."));
+			PVR_LOG(("Extra options present in client-side driver: (0x%x). Please check sgx_options.h",
+					 psDevInfo->ui32ClientBuildOptions & ui32BuildOptionsMismatch));
+		}
+
+		if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in client-side and KM driver build options."));
+			PVR_LOG(("Extra options present in KM: (0x%x). Please check sgx_options.h",
+					 ui32BuildOptions & ui32BuildOptionsMismatch));
+		}
+		eError = PVRSRV_ERROR_BUILD_MISMATCH;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Client-side and KM driver build options match. [ OK ]"));
+	}
+
+#if !defined (NO_HARDWARE)
+	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+	/* Clear state (not strictly necessary since this is the first call) */
+	psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+	psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
+	psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
+	eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, IMG_NULL);
+
+	if(eError != PVRSRV_OK)
+	{
+		PVR_LOG(("(FAIL) SGXInit: Unable to validate hardware core revision"));
+		goto chk_exit;
+	}
+	psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+	/*
+	 * 	Check hardware core revision is compatible with the one in software
+	 */
+	if (psSGXFeatures->ui32CoreRevSW == 0)
+	{
+		/*
+			Head core revision cannot be checked.
+		*/
+		PVR_LOG(("SGXInit: HW core rev (%x) check skipped.",
+				psSGXFeatures->ui32CoreRev));
+	}
+	else
+	{
+		/* For some cores the hw/sw core revisions are expected not to match. For these
+		 * exceptional cases the core rev compatibility check should be skipped.
+		 */
+		bCheckCoreRev = IMG_TRUE;
+		for(i=0; i<ui32NumCoreExceptions; i+=2)
+		{
+			if( (psSGXFeatures->ui32CoreRev==aui32CoreRevExceptions[i]) &&
+				(psSGXFeatures->ui32CoreRevSW==aui32CoreRevExceptions[i+1])	)
+			{
+				PVR_LOG(("SGXInit: HW core rev (%x), SW core rev (%x) check skipped.",
+						psSGXFeatures->ui32CoreRev,
+						psSGXFeatures->ui32CoreRevSW));
+				bCheckCoreRev = IMG_FALSE;
+			}
+		}
+
+		if (bCheckCoreRev)
+		{
+			if (psSGXFeatures->ui32CoreRev != psSGXFeatures->ui32CoreRevSW)
+			{
+				PVR_LOG(("(FAIL) SGXInit: Incompatible HW core rev (%x) and SW core rev (%x).",
+						psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+						eError = PVRSRV_ERROR_BUILD_MISMATCH;
+						goto chk_exit;
+			}
+			else
+			{
+				PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: HW core rev (%x) and SW core rev (%x) match. [ OK ]",
+						psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+			}
+		}
+	}
+
+	/*
+	 * 	Check ukernel structure sizes are the same as those in the driver
+	 */
+	psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
+
+	bStructSizesFailed = IMG_FALSE;
+
+	CHECK_SIZE(HOST_CTL);
+	CHECK_SIZE(COMMAND);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+	CHECK_SIZE(2DCMD);
+	CHECK_SIZE(2DCMD_SHARED);
+#endif
+	CHECK_SIZE(CMDTA);
+	CHECK_SIZE(CMDTA_SHARED);
+	CHECK_SIZE(TRANSFERCMD);
+	CHECK_SIZE(TRANSFERCMD_SHARED);
+
+	CHECK_SIZE(3DREGISTERS);
+	CHECK_SIZE(HWPBDESC);
+	CHECK_SIZE(HWRENDERCONTEXT);
+	CHECK_SIZE(HWRENDERDETAILS);
+	CHECK_SIZE(HWRTDATA);
+	CHECK_SIZE(HWRTDATASET);
+	CHECK_SIZE(HWTRANSFERCONTEXT);
+
+	if (bStructSizesFailed == IMG_TRUE)
+	{
+		PVR_LOG(("(FAIL) SGXInit: Mismatch in SGXMKIF structure sizes."));
+		eError = PVRSRV_ERROR_BUILD_MISMATCH;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
+	}
+
+	/*
+	 * Check ukernel build options against KM host driver
+	 */
+
+	ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
+	if (ui32BuildOptions != (SGX_BUILD_OPTIONS))
+	{
+		ui32BuildOptionsMismatch = ui32BuildOptions ^ (SGX_BUILD_OPTIONS);
+		if ( ((SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+				"extra options present in driver: (0x%x). Please check sgx_options.h",
+				(SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch ));
+		}
+
+		if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+		{
+			PVR_LOG(("(FAIL) SGXInit: Mismatch in driver and microkernel build options; "
+				"extra options present in microkernel: (0x%x). Please check sgx_options.h",
+				ui32BuildOptions & ui32BuildOptionsMismatch ));
+		}
+		eError = PVRSRV_ERROR_BUILD_MISMATCH;
+		goto chk_exit;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Driver and microkernel build options match. [ OK ]"));
+	}
+#endif // NO_HARDWARE
+
+	eError = PVRSRV_OK;
+chk_exit:
+#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK)
+	return PVRSRV_OK;
+#else
+	return eError;
+#endif
+}
+
+/*
+ * @Function	SGXGetMiscInfoUkernel
+ *
+ * @Description	Returns misc info (e.g. SGX build info/flags) from microkernel
+ *
+ * @Input	psDevInfo : device info from init phase
+ * @Input	psDeviceNode : device node, used for scheduling ukernel to query SGX features
+ *
+ * @Return	PVRSRV_ERROR :
+ *
+ */
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO	*psDevInfo,
+								   PVRSRV_DEVICE_NODE 	*psDeviceNode,
+								   IMG_HANDLE hDevMemContext)
+{
+	PVRSRV_ERROR		eError;
+	SGXMKIF_COMMAND		sCommandData;  /* CCB command data */
+	PVRSRV_SGX_MISCINFO_INFO			*psSGXMiscInfoInt; 	/*!< internal misc info for ukernel */
+	PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;		/*!< sgx features for client */
+	SGX_MISCINFO_STRUCT_SIZES			*psSGXStructSizes;	/*!< internal info: microkernel structure sizes */
+
+	PPVRSRV_KERNEL_MEM_INFO	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+	if (! psMemInfo->pvLinAddrKM)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Invalid address."));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+	psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+	psSGXStructSizes = &psSGXMiscInfoInt->sSGXStructSizes;
+
+	psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+
+	/* Reset SGX features */
+	OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+	OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
+
+	/* set up buffer address for SGX features in CCB */
+	sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr; /* device V addr of output buffer */
+
+	PDUMPCOMMENT("Microkernel kick for SGXGetMiscInfo");
+	eError = SGXScheduleCCBCommandKM(psDeviceNode,
+									 SGXMKIF_CMD_GETMISCINFO,
+									 &sCommandData,
+									 KERNEL_ID,
+									 0,
+									 hDevMemContext,
+									 IMG_FALSE);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: SGXScheduleCCBCommandKM failed."));
+		return eError;
+	}
+
+	/* FIXME: DWORD value to determine code path in ukernel?
+	 * E.g. could use getMiscInfo to obtain register values for diagnostics? */
+
+#if !defined(NO_HARDWARE)
+	{
+		IMG_BOOL bExit;
+
+		bExit = IMG_FALSE;
+		LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+		{
+			if ((psSGXMiscInfoInt->ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) != 0)
+			{
+				bExit = IMG_TRUE;
+				break;
+			}
+		} END_LOOP_UNTIL_TIMEOUT();
+
+		/*if the loop exited because a timeout*/
+		if (!bExit)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
+			return PVRSRV_ERROR_TIMEOUT;
+		}
+	}
+#endif /* NO_HARDWARE */
+
+	return PVRSRV_OK;
+}
+
+
+
+/*
+ * @Function	SGXGetMiscInfoKM
+ *
+ * @Description	Returns miscellaneous SGX info
+ *
+ * @Input	psDevInfo : device info from init phase
+ * @Input	psDeviceNode : device node, used for scheduling ukernel to query SGX features
+ *
+ * @Output	psMiscInfo : query request plus user-mode mem for holding returned data
+ *
+ * @Return	PVRSRV_ERROR :
+ *
+ */
+IMG_EXPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							  SGX_MISC_INFO			*psMiscInfo,
+ 							  PVRSRV_DEVICE_NODE 	*psDeviceNode,
+ 							  IMG_HANDLE 			 hDevMemContext)
+{
+	PVRSRV_ERROR eError;
+	PPVRSRV_KERNEL_MEM_INFO	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+	IMG_UINT32	*pui32MiscInfoFlags;
+	pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
+
+#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+	PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+	switch(psMiscInfo->eRequest)
+	{
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+		case SGX_MISC_INFO_REQUEST_SET_BREAKPOINT:
+		{
+			IMG_UINT32      ui32MaskDM;
+			IMG_UINT32      ui32CtrlWEnable;
+			IMG_UINT32      ui32CtrlREnable;
+			IMG_UINT32      ui32CtrlTrapEnable;
+			IMG_UINT32		ui32RegVal;
+			IMG_UINT32		ui32StartRegVal;
+			IMG_UINT32		ui32EndRegVal;
+			SGXMKIF_COMMAND	sCommandData;
+
+			/* Set or Clear BP? */
+			if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
+			{
+				/* set the break point */
+				IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
+				IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd;
+
+				/* BP address */
+				ui32StartRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_START_ADDRESS_MASK;
+				ui32EndRegVal = sBPDevVAddrEnd.uiAddr & EUR_CR_BREAKPOINT0_END_ADDRESS_MASK;
+
+				ui32MaskDM = psMiscInfo->uData.sSGXBreakpointInfo.ui32DataMasterMask;
+				ui32CtrlWEnable = psMiscInfo->uData.sSGXBreakpointInfo.bWrite;
+				ui32CtrlREnable = psMiscInfo->uData.sSGXBreakpointInfo.bRead;
+				ui32CtrlTrapEnable = psMiscInfo->uData.sSGXBreakpointInfo.bTrapped;
+
+				/* normal data BP */
+				ui32RegVal = ((ui32MaskDM<<EUR_CR_BREAKPOINT0_MASK_DM_SHIFT) & EUR_CR_BREAKPOINT0_MASK_DM_MASK) |
+							 ((ui32CtrlWEnable<<EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK) |
+							 ((ui32CtrlREnable<<EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK) |
+							 ((ui32CtrlTrapEnable<<EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK);
+			}
+			else
+			{
+				/* clear the break point */
+				ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0;
+			}
+
+			/* setup the command */
+			sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex;
+			sCommandData.ui32Data[1] = ui32StartRegVal;
+			sCommandData.ui32Data[2] = ui32EndRegVal;
+			sCommandData.ui32Data[3] = ui32RegVal;
+
+			/* clear signal flags */
+			psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+
+			PDUMPCOMMENT("Microkernel kick for setting a data breakpoint");
+			eError = SGXScheduleCCBCommandKM(psDeviceNode,
+											 SGXMKIF_CMD_DATABREAKPOINT,
+											 &sCommandData,
+											 KERNEL_ID,
+											 0,
+											 hDevMemContext,
+											 IMG_FALSE);
+
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed."));
+				return eError;
+			}
+
+#if defined(NO_HARDWARE)
+			/* clear signal flags */
+			psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+#else
+			{
+				IMG_BOOL bExit;
+
+				bExit = IMG_FALSE;
+				LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+				{
+					if (psDevInfo->psSGXHostCtl->ui32BPSetClearSignal != 0)
+					{
+						bExit = IMG_TRUE;
+						/* clear signal flags */
+						psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+						break;
+					}
+				} END_LOOP_UNTIL_TIMEOUT();
+
+				/*if the loop exited because a timeout*/
+				if (!bExit)
+				{
+					PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear"));
+					return PVRSRV_ERROR_TIMEOUT;
+				}
+			}
+#endif /* NO_HARDWARE */
+
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT:
+		{
+			/* This request checks to see whether a breakpoint has
+			   been trapped.  If so, it returns the number of the
+			   breakpoint number that was trapped in ui32BPIndex,
+			   sTrappedBPDevVAddr to the address which was trapped,
+			   and sets bTrappedBP.  Otherwise, bTrappedBP will be
+			   false, and other fields should be ignored. */
+			/* The uKernel is not used, since if we are stopped on a
+			   breakpoint, it is not possible to guarantee that the
+			   uKernel would be able to run */
+#if !defined(NO_HARDWARE)
+#if defined(SGX_FEATURE_MP)
+			IMG_BOOL bTrappedBPMaster;
+			IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum;
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+			IMG_UINT32 ui32PipeNum, ui32TrappedBPPipeNum;
+/* ui32PipeNum is the pipe number plus 1, or 0 to represent "partition" */
+#define NUM_PIPES_PLUS_ONE (SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES+1)
+#endif
+			IMG_BOOL bTrappedBPAny;
+#endif /* defined(SGX_FEATURE_MP) */
+			IMG_BOOL bFoundOne;
+
+#if defined(SGX_FEATURE_MP)
+			ui32TrappedBPCoreNum = 0;
+			bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT));
+			bTrappedBPAny = bTrappedBPMaster;
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+			ui32TrappedBPPipeNum = 0; /* just to keep the (incorrect) compiler happy */
+#endif
+			for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
+			{
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+				/* FIXME:  this macro makes the assumption that the PARTITION regs are the same
+				   distance before the PIPE0 regs as the PIPE1 regs are after it, _and_
+				   assumes that the fields in the partition regs are in the same place
+				   in the pipe regs.  Need to validate these assumptions, or assert them */
+#define SGX_MP_CORE_PIPE_SELECT(r,c,p) \
+				((SGX_MP_CORE_SELECT(EUR_CR_PARTITION_##r,c) + p*(EUR_CR_PIPE0_##r-EUR_CR_PARTITION_##r)))
+				for (ui32PipeNum = 0; ui32PipeNum < NUM_PIPES_PLUS_ONE; ui32PipeNum++)
+				{
+					bFoundOne =
+						0 != (EUR_CR_PARTITION_BREAKPOINT_TRAPPED_MASK & 
+							  OSReadHWReg(psDevInfo->pvRegsBaseKM, 
+										  SGX_MP_CORE_PIPE_SELECT(BREAKPOINT,
+																  ui32CoreNum,
+																  ui32PipeNum)));
+					if (bFoundOne)
+					{
+						bTrappedBPAny = IMG_TRUE;
+						ui32TrappedBPCoreNum = ui32CoreNum;
+						ui32TrappedBPPipeNum = ui32PipeNum;
+					}
+				}
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+				bFoundOne = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)));
+				if (bFoundOne)
+				{
+					bTrappedBPAny = IMG_TRUE;
+					ui32TrappedBPCoreNum = ui32CoreNum;
+				}
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+			}
+
+			psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny;
+#else /* defined(SGX_FEATURE_MP) */
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+			#error Not yet considered the case for per-pipe regs in non-mp case
+#endif
+			psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = 0 != (EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT));
+#endif /* defined(SGX_FEATURE_MP) */
+
+			if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP)
+			{
+				IMG_UINT32 ui32Info0, ui32Info1;
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+				ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
+				ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+				ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum));
+				ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum));
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#else /* defined(SGX_FEATURE_MP) */
+				ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO0);
+				ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO1);
+#endif /* defined(SGX_FEATURE_MP) */
+
+#ifdef SGX_FEATURE_PERPIPE_BKPT_REGS
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
+				psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
+				psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK);
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
+				psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
+				psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK);
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+				/* mp, per-pipe regbanks */
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:(ui32TrappedBPCoreNum + (ui32TrappedBPPipeNum<<10));
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+				/* mp, regbanks unsplit */
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum;
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#else /* defined(SGX_FEATURE_MP) */
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+				/* non-mp, per-pipe regbanks */
+#error non-mp perpipe regs not yet supported
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+				/* non-mp */
+				psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = 65534;
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#endif /* defined(SGX_FEATURE_MP) */
+			}
+#endif /* !defined(NO_HARDWARE) */
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT:
+		{
+			/* This request resumes from the currently trapped breakpoint. */
+			/* Core number must be supplied */
+			/* Polls for notify to be acknowledged by h/w */
+#if !defined(NO_HARDWARE)
+#if defined(SGX_FEATURE_MP)
+			IMG_UINT32 ui32CoreNum;
+			IMG_BOOL bMaster;
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+			IMG_UINT32 ui32PipeNum;
+#endif
+#endif /* defined(SGX_FEATURE_MP) */
+			IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum;
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+			ui32PipeNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum >> 10;
+			ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum & 1023;
+			bMaster = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum > 32767;
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+			ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum;
+			bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT_3D;
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+			if (bMaster)
+			{
+				/* master */
+				/* EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK | EUR_CR_MASTER_BREAKPOINT_SEQNUM_MASK */
+				ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+				OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT_TRAP, EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK);
+				do
+				{
+					ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+				}
+				while (ui32OldSeqNum == ui32NewSeqNum);
+			}
+			else
+#endif /* defined(SGX_FEATURE_MP) */
+			{
+				/* core */
+#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
+				ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
+				OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP, ui32CoreNum, ui32PipeNum), EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK);
+				do
+				{
+					ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
+				}
+				while (ui32OldSeqNum == ui32NewSeqNum);
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+				ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+				OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP, ui32CoreNum), EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
+				do
+				{
+					ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+				}
+				while (ui32OldSeqNum == ui32NewSeqNum);
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+			}
+#endif /* !defined(NO_HARDWARE) */
+			return PVRSRV_OK;
+		}
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS)	*/
+
+		case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+		{
+			psMiscInfo->uData.ui32SGXClockSpeed = psDevInfo->ui32CoreClockSpeed;
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_CLOCKSPEED_SLCSIZE:
+		{
+			psMiscInfo->uData.sQueryClockSpeedSLCSize.ui32SGXClockSpeed = SYS_SGX_CLOCK_SPEED;
+#if defined(SGX_FEATURE_SYSTEM_CACHE) && defined(SYS_SGX_SLC_SIZE)
+			psMiscInfo->uData.sQueryClockSpeedSLCSize.ui32SGXSLCSize = SYS_SGX_SLC_SIZE;
+#else
+			psMiscInfo->uData.sQueryClockSpeedSLCSize.ui32SGXSLCSize = 0;
+#endif /* defined(SGX_FEATURE_SYSTEM_CACHE) && defined(SYS_SGX_SLC_SIZE) */
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_ACTIVEPOWER:
+		{
+			psMiscInfo->uData.sActivePower.ui32NumActivePowerEvents = psDevInfo->psSGXHostCtl->ui32NumActivePowerEvents;
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_LOCKUPS:
+		{
+#if defined(SUPPORT_HW_RECOVERY)
+			psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = psDevInfo->psSGXHostCtl->ui32uKernelDetectedLockups;
+			psMiscInfo->uData.sLockups.ui32HostDetectedLockups = psDevInfo->psSGXHostCtl->ui32HostDetectedLockups;
+#else
+			psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = 0;
+			psMiscInfo->uData.sLockups.ui32HostDetectedLockups = 0;
+#endif
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_SPM:
+		{
+			/* this is dealt with in UM */
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_SGXREV:
+		{
+			PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;
+//			PPVRSRV_KERNEL_MEM_INFO	psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+			eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, hDevMemContext);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+						eError));
+				return eError;
+			}
+			psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+			/* Copy SGX features into misc info struct, to return to client */
+			psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+			/* Debug output */
+			PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%x, sw ID 0x%x, sw Rev 0x%x\n",
+					psSGXFeatures->ui32CoreRev,
+					psSGXFeatures->ui32CoreIdSW,
+					psSGXFeatures->ui32CoreRevSW));
+			PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: DDK version 0x%x, DDK build 0x%x\n",
+					psSGXFeatures->ui32DDKVersion,
+					psSGXFeatures->ui32DDKBuild));
+
+			/* done! */
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+		{
+			PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;
+
+			psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+			/* Reset the misc information to prevent
+			 * confusion with values returned from the ukernel
+			 */
+			OSMemSet(psMemInfo->pvLinAddrKM, 0,
+					sizeof(PVRSRV_SGX_MISCINFO_INFO));
+
+			psSGXFeatures->ui32DDKVersion =
+				(PVRVERSION_MAJ << 16) |
+				(PVRVERSION_MIN << 8);
+			psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
+
+			/* Also report the kernel module build options -- used in SGXConnectionCheck() */
+			psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS);
+
+			/* Copy SGX features into misc info struct, to return to client */
+			psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+			return PVRSRV_OK;
+		}
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+		case SGX_MISC_INFO_REQUEST_EDM_STATUS_BUFFER_INFO:
+		{
+			/* Report the EDM status buffer location in memory */
+			psMiscInfo->uData.sEDMStatusBufferInfo.sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr;
+			psMiscInfo->uData.sEDMStatusBufferInfo.pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+			return PVRSRV_OK;
+		}
+#endif
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+		case SGX_MISC_INFO_REQUEST_MEMREAD:
+		case SGX_MISC_INFO_REQUEST_MEMCOPY:
+		{
+			PVRSRV_ERROR eError;
+			PVRSRV_SGX_MISCINFO_FEATURES		*psSGXFeatures;
+			PVRSRV_SGX_MISCINFO_MEMACCESS		*psSGXMemSrc;	/* user-defined mem read */
+			PVRSRV_SGX_MISCINFO_MEMACCESS		*psSGXMemDest;	/* user-defined mem write */
+
+			{				
+				*pui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_MEMREAD;
+				/* Set the mem read flag; src is user-defined */
+				*pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
+				psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc;
+
+				if(psMiscInfo->sDevVAddrSrc.uiAddr != 0)
+				{
+					psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc; /* src address */
+				}
+				else
+				{
+					return PVRSRV_ERROR_INVALID_PARAMS;
+				}				
+			}
+
+			if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY)
+			{				
+				*pui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_MEMWRITE;
+				/* Set the mem write flag; dest is user-defined */
+				*pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE;
+				psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest;
+				
+				if(psMiscInfo->sDevVAddrDest.uiAddr != 0)
+				{
+					psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest; /* dest address */
+				}
+				else
+				{
+					return PVRSRV_ERROR_INVALID_PARAMS;
+				}
+			}
+
+			/* Get physical address of PD for memory read (may need to switch context in microkernel) */
+			if(psMiscInfo->hDevMemContext != IMG_NULL)
+			{
+				SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr);
+				
+				/* Single app will always use the same src and dest mem context */
+				psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr;
+			}
+			else
+			{
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+			/* Submit the task to the ukernel */
+			eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+			if(eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+						eError));
+				return eError;
+			}
+			psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+			if(*pui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_MEMREAD_FAIL)
+			{
+				return PVRSRV_ERROR_INVALID_MISCINFO;
+			}
+#endif
+			/* Copy SGX features into misc info struct, to return to client */
+			psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+			return PVRSRV_OK;
+		}
+#endif /* SUPPORT_SGX_EDM_MEMORY_DEBUG */
+
+#if defined(SUPPORT_SGX_HWPERF)
+		case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+		{
+			PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS	*psSetHWPerfStatus = &psMiscInfo->uData.sSetHWPerfStatus;
+			const IMG_UINT32	ui32ValidFlags = PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS |
+												 PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON |
+												 PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON |
+												 PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON;
+			SGXMKIF_COMMAND		sCommandData = {0};
+
+			/* Check for valid flags */
+			if ((psSetHWPerfStatus->ui32NewHWPerfStatus & ~ui32ValidFlags) != 0)
+			{
+				return PVRSRV_ERROR_INVALID_PARAMS;
+			}
+
+			#if defined(PDUMP)
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+								  "SGX ukernel HWPerf status %u\n",
+								  psSetHWPerfStatus->ui32NewHWPerfStatus);
+			#endif /* PDUMP */
+
+			/* Copy the new group selector(s) to the host ctl for the ukernel */
+			#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+			OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfGroup[0],
+					  &psSetHWPerfStatus->aui32PerfGroup[0],
+					  sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup));
+			OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfBit[0],
+					  &psSetHWPerfStatus->aui32PerfBit[0],
+					  sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit));
+			psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect = psSetHWPerfStatus->ui32PerfCounterBitSelect;
+			psDevInfo->psSGXHostCtl->ui32PerfSumMux = psSetHWPerfStatus->ui32PerfSumMux;
+			#if defined(PDUMP)
+			PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+					 offsetof(SGXMKIF_HOST_CTL, aui32PerfGroup),
+					 sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup),
+					 PDUMP_FLAGS_CONTINUOUS,
+					 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+			PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+					 offsetof(SGXMKIF_HOST_CTL, aui32PerfBit),
+					 sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit),
+					 PDUMP_FLAGS_CONTINUOUS,
+					 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+			PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+					 offsetof(SGXMKIF_HOST_CTL, ui32PerfCounterBitSelect),
+					 sizeof(psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect),
+					 PDUMP_FLAGS_CONTINUOUS,
+					 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+			PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+					 offsetof(SGXMKIF_HOST_CTL, ui32PerfSumMux),
+					 sizeof(psDevInfo->psSGXHostCtl->ui32PerfSumMux),
+					 PDUMP_FLAGS_CONTINUOUS,
+					 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+			#endif /* PDUMP */
+			#else
+			psDevInfo->psSGXHostCtl->ui32PerfGroup = psSetHWPerfStatus->ui32PerfGroup;
+			#if defined(PDUMP)
+			PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+					 offsetof(SGXMKIF_HOST_CTL, ui32PerfGroup),
+					 sizeof(psDevInfo->psSGXHostCtl->ui32PerfGroup),
+					 PDUMP_FLAGS_CONTINUOUS,
+					 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+			#endif /* PDUMP */
+			#endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
+
+			/* Kick the ukernel to update the hardware state */
+			sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus;
+			eError = SGXScheduleCCBCommandKM(psDeviceNode,
+											 SGXMKIF_CMD_SETHWPERFSTATUS,
+											 &sCommandData,
+											 KERNEL_ID,
+											 0,
+											 hDevMemContext,
+											 IMG_FALSE);
+			return eError;
+		}
+#endif /* SUPPORT_SGX_HWPERF */
+
+		case SGX_MISC_INFO_DUMP_DEBUG_INFO:
+		{
+			PVR_LOG(("User requested SGX debug info"));
+
+			/* Dump SGX debug data to the kernel log. */
+			SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE);
+
+			return PVRSRV_OK;
+		}
+
+		case SGX_MISC_INFO_DUMP_DEBUG_INFO_FORCE_REGS:
+		{
+			if(!OSProcHasPrivSrvInit())
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Insufficient privileges to dump SGX "
+										"debug info with registers"));
+
+				return PVRSRV_ERROR_INVALID_MISCINFO;
+			}
+
+			PVR_LOG(("User requested SGX debug info"));
+
+			/* Dump SGX debug data to the kernel log. */
+			SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+
+			return PVRSRV_OK;
+		}
+
+#if defined(DEBUG)
+		/* Don't allow user-mode to reboot the device in production drivers */
+		case SGX_MISC_INFO_PANIC:
+		{
+			PVR_LOG(("User requested SGX panic"));
+
+			SGXPanic(psDeviceNode->pvDevice);
+
+			return PVRSRV_OK;
+		}
+#endif
+
+		default:
+		{
+			/* switch statement fell though, so: */
+			return PVRSRV_ERROR_INVALID_PARAMS;
+		}
+	}
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE					hDevHandle,
+							   IMG_UINT32					ui32ArraySize,
+							   PVRSRV_SGX_HWPERF_CB_ENTRY	*psClientHWPerfEntry,
+							   IMG_UINT32					*pui32DataCount,
+							   IMG_UINT32					*pui32ClockSpeed,
+							   IMG_UINT32					*pui32HostTimeStamp)
+{
+	PVRSRV_ERROR    	eError = PVRSRV_OK;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HWPERF_CB	*psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+	IMG_UINT			i;
+
+	for (i = 0;
+		 psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+		 i++)
+	{
+		SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+		psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+		psClientHWPerfEntry[i].ui32PID = psMKPerfEntry->ui32PID;
+		psClientHWPerfEntry[i].ui32RTData = psMKPerfEntry->ui32RTData;
+		psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+		psClientHWPerfEntry[i].ui32Ordinal	= psMKPerfEntry->ui32Ordinal;
+		psClientHWPerfEntry[i].ui32Info	= psMKPerfEntry->ui32Info;
+		psClientHWPerfEntry[i].ui32Clocksx16 = SGXConvertTimeStamp(psDevInfo,
+													psMKPerfEntry->ui32TimeWraps,
+													psMKPerfEntry->ui32Time);
+		OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0][0],
+				  &psMKPerfEntry->ui32Counters[0][0],
+				  sizeof(psMKPerfEntry->ui32Counters));
+
+		OSMemCopy(&psClientHWPerfEntry[i].ui32MiscCounters[0][0],
+				  &psMKPerfEntry->ui32MiscCounters[0][0],
+				  sizeof(psMKPerfEntry->ui32MiscCounters));
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+		psClientHWPerfEntry[i].ui32SystraceIndex	= psMKPerfEntry->ui32SystraceIndex;
+#endif
+
+		psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+	}
+
+	*pui32DataCount = i;
+	*pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+	*pui32HostTimeStamp = OSClockus();
+
+	return eError;
+}
+
+
+/******************************************************************************
+ End of file (sgxinit.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxkick.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxkick.c
new file mode 100644
index 0000000..e15670d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxkick.c
@@ -0,0 +1,811 @@
+/*************************************************************************/ /*!
+@Title          Device specific kickTA routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h> /* For the macro offsetof() */
+#include "services_headers.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#if defined (PDUMP)
+#include "sgxapi_km.h"
+#include "pdump_km.h"
+#endif
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include "pvr_sync_common.h"
+#endif
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+#include "systrace.h"
+#endif
+
+#if defined(SUPPORT_DMABUF)
+#include "pvr_linux_fence.h"
+#endif
+
+/*!
+******************************************************************************
+
+ @Function	SGXDoKickKM
+
+ @Description
+
+ Really kicks the TA
+
+ @Input hDevHandle - Device handle
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_KERNEL_SYNC_INFO	*psSyncInfo;
+	PVRSRV_KERNEL_MEM_INFO	*psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo;
+	SGXMKIF_CMDTA_SHARED *psTACmd;
+	IMG_UINT32 i;
+	IMG_HANDLE hDevMemContext = IMG_NULL;
+	IMG_HANDLE *pahDstSyncHandles;
+#if defined(SUPPORT_DMABUF)
+	IMG_UINT32 ui32FenceTag = 0;
+	IMG_UINT32 ui32NumResvObjs = 0;
+	IMG_BOOL bBlockingFences = IMG_FALSE;
+#endif
+#if  (defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER))
+	PVRSRV_DEVICE_NODE      *psDeviceNode;
+	PVRSRV_SGXDEV_INFO      *psDevInfo;
+
+	psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+	psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+#endif
+#if defined(FIX_HW_BRN_31620)
+	hDevMemContext = psCCBKick->hDevMemContext;
+#endif
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_ENTER, KICK_TOKEN_DOKICK);
+
+	if (!CCB_OFFSET_IS_VALID(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset"));
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT, KICK_TOKEN_DOKICK);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	/* override QAC warning about stricter alignment */
+	/* PRQA S 3305 1 */
+	psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_START, KICK_TOKEN_DOKICK);
+
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FRAMENUM, KICK_TOKEN_FRAMENUM, psCCBKick->ui32FrameNum);
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_NONE, KICK_TOKEN_RENDERCONTEXT, psCCBKick->sCommand.ui32Data[1]);
+	PVR_TTRACE_DEV_VIRTADDR(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_DEVVADDR, KICK_TOKEN_HWRTDATASET, psCCBKick->sHWRTDataSetDevAddr);
+	PVR_TTRACE_DEV_VIRTADDR(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_DEVVADDR, KICK_TOKEN_HWRTDATA, psCCBKick->sHWRTDataDevAddr);
+
+#if defined(TTRACE)
+	if (psCCBKick->bFirstKickOrResume)
+	{
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK,
+				   PVRSRV_TRACE_CLASS_FLAGS,
+				   KICK_TOKEN_FIRST_KICK);
+	}
+
+	if (psCCBKick->bLastInScene)
+	{
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK,
+				   PVRSRV_TRACE_CLASS_FLAGS,
+				   KICK_TOKEN_LAST_KICK);
+	}
+#endif
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CCB,
+			KICK_TOKEN_CCB_OFFSET, psCCBKick->ui32CCBOffset);
+
+	/* TA/3D dependency */
+	if (psCCBKick->hTA3DSyncInfo)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_TA3D_SYNC,
+					  psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+		psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+		psTACmd->sTA3DDependency.ui32WriteOpsPendingVal   = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+		if (psCCBKick->bTADependency)
+		{
+			SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		}
+	}
+
+	if (psCCBKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_TA_SYNC,
+					  psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+		psTACmd->sTATQSyncReadOpsCompleteDevVAddr  = psSyncInfo->sReadOpsCompleteDevVAddr;
+		psTACmd->sTATQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+		psTACmd->ui32TATQSyncReadOpsPendingVal = SyncTakeReadOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		psTACmd->ui32TATQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	if (psCCBKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_3D_SYNC,
+					  psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+		psTACmd->s3DTQSyncReadOpsCompleteDevVAddr  = psSyncInfo->sReadOpsCompleteDevVAddr;
+		psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+		psTACmd->ui323DTQSyncReadOpsPendingVal = SyncTakeReadOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		psTACmd->ui323DTQSyncWriteOpsPendingVal  = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+	if (psCCBKick->ui32NumTAStatusVals != 0)
+	{
+		/* Copy status vals over */
+		for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			psTACmd->sCtlTAStatusInfo[i] = psCCBKick->asTAStatusUpdate[i].sCtlStatus;
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+			psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+			psTACmd->sCtlTAStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+		}
+	}
+
+	psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+	if (psCCBKick->ui32Num3DStatusVals != 0)
+	{
+		/* Copy status vals over */
+		for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			psTACmd->sCtl3DStatusInfo[i] = psCCBKick->as3DStatusUpdate[i].sCtlStatus;
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+			psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+			psTACmd->sCtl3DStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+		}
+	}
+
+
+	/* texture dependencies */
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	eError = PVRSyncPatchCCBKickSyncInfos(psCCBKick->ahSrcKernelSyncInfo,
+										  psTACmd->asSrcSyncs,
+										  &psCCBKick->ui32NumSrcSyncs);
+	if(eError != PVRSRV_OK)
+	{
+		/* We didn't kick yet, or perform PDUMP processing, so we should
+		 * be able to trivially roll back any changes made to the sync
+		 * data. If we don't do this, we'll wedge services cleanup.
+		 */
+
+		if (psCCBKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+		}
+
+		if (psCCBKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+		}
+
+		if (psCCBKick->hTA3DSyncInfo && psCCBKick->bTADependency)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+			psSyncInfo->psSyncData->ui32WriteOpsPending--;
+		}
+
+		PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: PVRSyncPatchCCBKickSyncInfos failed."));
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+				   KICK_TOKEN_DOKICK);
+		return eError;
+	}
+#else /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+#if defined(SUPPORT_DMABUF)
+	ui32NumResvObjs = PVRLinuxFenceNumResvObjs(&bBlockingFences,
+			psCCBKick->ui32NumSrcSyncs,
+			psCCBKick->ahSrcKernelSyncInfo,
+			NULL,
+			psCCBKick->bFirstKickOrResume ? psCCBKick->ui32NumDstSyncObjects : 0,
+			(IMG_HANDLE*)psCCBKick->hDstSyncHandles,
+			NULL);
+	/*
+	 * If there are no blocking fences, the GPU need not wait whilst
+	 * the reservation objects are being processed. They can be processed
+	 * later, after the kick.
+	 */
+	if (ui32NumResvObjs && bBlockingFences)
+	{
+		eError = PVRLinuxFenceProcess(&ui32FenceTag,
+				ui32NumResvObjs,
+				bBlockingFences,
+				psCCBKick->ui32NumSrcSyncs,
+				psCCBKick->ahSrcKernelSyncInfo,
+				NULL,
+				psCCBKick->bFirstKickOrResume ? psCCBKick->ui32NumDstSyncObjects : 0,
+				(IMG_HANDLE*)psCCBKick->hDstSyncHandles,
+				NULL);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+#endif
+	for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_SRC_SYNC,
+					  psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+		psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+		/* Get ui32ReadOpsPending snapshot and copy into the CCB - before incrementing. */
+		psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = SyncTakeReadOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		/* Copy ui32WriteOpsPending snapshot into the CCB. */
+		psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+	psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+
+	if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+	{
+		PVRSRV_KERNEL_MEM_INFO	*psHWDstSyncListMemInfo =
+								(PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+		SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+		IMG_UINT32	ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
+
+		PVR_ASSERT(((PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo)->uAllocSize >= (sizeof(SGXMKIF_HWDEVICE_SYNC_LIST) +
+								(sizeof(PVRSRV_DEVICE_SYNC_OBJECT) * ui32NumDstSyncs)));
+
+		psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
+#if defined(PDUMP)
+		if (PDumpIsCaptureFrameKM())
+		{
+			PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
+			PDUMPMEM(IMG_NULL,
+					 psHWDstSyncListMemInfo,
+					 0,
+					 sizeof(SGXMKIF_HWDEVICE_SYNC_LIST),
+					 0,
+					 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+		}
+#endif
+		pahDstSyncHandles = psCCBKick->hDstSyncHandles;
+		for (i=0; i<ui32NumDstSyncs; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pahDstSyncHandles[i];
+
+			if (psSyncInfo)
+			{
+				psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
+
+				PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_DST_SYNC,
+							psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+				psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+				psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+				psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+
+				psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+				psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+				psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+	#if defined(PDUMP)
+				if (PDumpIsCaptureFrameKM())
+				{
+					IMG_UINT32 ui32ModifiedValue;
+					IMG_UINT32 ui32SyncOffset = offsetof(SGXMKIF_HWDEVICE_SYNC_LIST, asSyncData)
+												+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT));
+					IMG_UINT32 ui32WOpsOffset = ui32SyncOffset
+												+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
+					IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+												+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+					IMG_UINT32 ui32ROps2Offset = ui32SyncOffset
+												+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal);
+
+					PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
+
+					PDUMPMEM(IMG_NULL,
+							 psHWDstSyncListMemInfo,
+							 ui32SyncOffset,
+							 sizeof(PVRSRV_DEVICE_SYNC_OBJECT),
+							 0,
+							 MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+					psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+					ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+					PDUMPCOMMENT("Modify RT %d WOpPendingVal in HWDevSyncList\r\n", i);
+
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+					PDUMPCOMMENT("TA Dst: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+											psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+											ui32ModifiedValue);
+#endif
+					PDUMPMEM(&ui32ModifiedValue,
+						psHWDstSyncListMemInfo,
+						ui32WOpsOffset,
+						sizeof(IMG_UINT32),
+						0,
+						MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+					ui32ModifiedValue = 0;
+					PDUMPCOMMENT("Modify RT %d ROpsPendingVal in HWDevSyncList\r\n", i);
+
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+						 psHWDstSyncListMemInfo,
+						 ui32ROpsOffset,
+						 sizeof(IMG_UINT32),
+						 0,
+						MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+					/*
+					* Force the ROps2Complete value to 0.
+					*/
+					PDUMPCOMMENT("Modify RT %d ROps2PendingVal in HWDevSyncList\r\n", i);
+					PDUMPMEM(&ui32ModifiedValue,
+						psHWDstSyncListMemInfo,
+						ui32ROps2Offset,
+						sizeof(IMG_UINT32),
+						0,
+						MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+					PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT, "TA Dst: PDump sync update: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+											psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+											psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+				}
+	#endif	/* defined(PDUMP) */
+			}
+			else
+			{
+				psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
+				psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+				psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr.uiAddr = 0;
+
+				psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+				psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = 0;
+				psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
+			}
+		}
+	}
+	
+	/* 
+		NOTE: THIS MUST BE THE LAST THING WRITTEN TO THE TA COMMAND!
+		Set the ready for so the uKernel will process the command.
+	*/
+	psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
+
+#if defined(PDUMP)
+	if (PDumpIsCaptureFrameKM())
+	{
+		PDUMPCOMMENT("Shared part of TA command\r\n");
+
+		PDUMPMEM(psTACmd,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff,
+				 sizeof(SGXMKIF_CMDTA_SHARED),
+				 0,
+				 MAKEUNIQUETAG(psCCBMemInfo));
+
+		for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+		{
+			IMG_UINT32 	ui32ModifiedValue;
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+			ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+			PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
+
+			PDUMPMEM(&ui32ModifiedValue,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
+
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENT("TA Src: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				psCCBMemInfo,
+				psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+					(i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+				sizeof(IMG_UINT32),
+				0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT, "TA Src: PDump sync update: uiAddr = 0x%08x, ui32LastReadOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastReadOpDumpVal);
+#endif
+		}
+
+		if (psCCBKick->hTA3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+			PDUMPCOMMENT("Modify TA/3D dependency WOpPendingVal\r\n");
+
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENT("TA TADep: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, sTA3DDependency.ui32WriteOpsPendingVal),
+					sizeof(IMG_UINT32),
+					0,
+					MAKEUNIQUETAG(psCCBMemInfo));
+			
+			if (psCCBKick->bTADependency)
+			{
+				psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+				PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT, "TA TADep: PDump sync update: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+										psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+										psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+			}
+		}
+
+		if (psCCBKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+			PDUMPCOMMENT("Modify TA/TQ ROpPendingVal\r\n");
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui32TATQSyncReadOpsPendingVal),
+					sizeof(IMG_UINT32),
+					0,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Modify TA/TQ WOpPendingVal\r\n");
+
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENT("TA TATQ: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui32TATQSyncWriteOpsPendingVal),
+					sizeof(IMG_UINT32),
+					0,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+		}
+
+		if (psCCBKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+			PDUMPCOMMENT("Modify 3D/TQ ROpPendingVal\r\n");
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui323DTQSyncReadOpsPendingVal),
+					sizeof(IMG_UINT32),
+					0,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Modify 3D/TQ WOpPendingVal\r\n");
+
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENT("TA 3DTQ: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, ui323DTQSyncWriteOpsPendingVal),
+					sizeof(IMG_UINT32),
+					0,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+		}
+
+		for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+		{
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+			PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+		}
+
+		for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+		{
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+			PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+				 psCCBMemInfo,
+				 psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+				 sizeof(IMG_UINT32),
+				 0,
+				MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+		}
+	}
+#endif	/* defined(PDUMP) */
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_END,
+			KICK_TOKEN_DOKICK);
+
+	eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TA, &psCCBKick->sCommand, KERNEL_ID, 0, hDevMemContext, psCCBKick->bLastInScene);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+#if defined(SUPPORT_DMABUF)
+		if (ui32NumResvObjs && bBlockingFences)
+		{
+			PVRLinuxFenceRelease(ui32FenceTag,
+				psCCBKick->ui32NumSrcSyncs,
+				psCCBKick->ahSrcKernelSyncInfo,
+				NULL,
+				psCCBKick->bFirstKickOrResume ? psCCBKick->ui32NumDstSyncObjects : 0,
+				(IMG_HANDLE*)psCCBKick->hDstSyncHandles,
+				NULL);
+		}
+#endif
+		if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+		{
+			pahDstSyncHandles = psCCBKick->hDstSyncHandles;
+			for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
+			{
+				/* Client will retry, so undo the write ops pending increment done above. */
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pahDstSyncHandles[i];
+
+				if (psSyncInfo)
+				{
+					psSyncInfo->psSyncData->ui32WriteOpsPending--;
+					SyncRollBackWriteOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+#if defined(PDUMP)
+					if (PDumpIsCaptureFrameKM())
+					{
+						psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+					}
+#endif
+				}
+			}
+		}
+
+		for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+			SyncRollBackReadOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		}
+
+		if (psCCBKick->hTA3DSyncInfo)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+			SyncRollBackReadOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		}
+	
+		if (psCCBKick->hTASyncInfo)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+			SyncRollBackReadOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		}
+	
+		if (psCCBKick->h3DSyncInfo)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+			psSyncInfo->psSyncData->ui32ReadOpsPending--;
+			SyncRollBackReadOp(psSyncInfo, SYNC_OP_CLASS_KICKTA);
+		}
+
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+				KICK_TOKEN_DOKICK);
+		return eError;
+	}
+	else if (PVRSRV_OK != eError)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: SGXScheduleCCBCommandKM failed."));
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+				KICK_TOKEN_DOKICK);
+#if defined(SUPPORT_DMABUF) && defined(NO_HARDWARE)
+		PVRLinuxFenceCheckAll();
+#endif
+		return eError;
+	}
+#if defined(SUPPORT_DMABUF)
+	else if (ui32NumResvObjs && !bBlockingFences)
+	{
+		eError = PVRLinuxFenceProcess(&ui32FenceTag,
+				ui32NumResvObjs,
+				bBlockingFences,
+				psCCBKick->ui32NumSrcSyncs,
+				psCCBKick->ahSrcKernelSyncInfo,
+				NULL,
+				psCCBKick->bFirstKickOrResume ? psCCBKick->ui32NumDstSyncObjects : 0,
+				(IMG_HANDLE*)psCCBKick->hDstSyncHandles,
+				NULL);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+#endif
+
+
+#if defined(NO_HARDWARE)
+
+
+	/* TA/3D dependency */
+	if (psCCBKick->hTA3DSyncInfo)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+		if (psCCBKick->bTADependency)
+		{
+			psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		}
+	}
+
+	if (psCCBKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+	if (psCCBKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+	/* Copy status vals over */
+	for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+	{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+		PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
+		/* derive offset into meminfo and write the status value */
+		*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+						+ (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
+						- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#else
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#endif
+	}
+
+	/* texture dependencies */
+	for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete =  psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+	if (psCCBKick->bTerminateOrAbort)
+	{
+		if (psCCBKick->ui32NumDstSyncObjects > 0)
+		{
+			PVRSRV_KERNEL_MEM_INFO	*psHWDstSyncListMemInfo =
+								(PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+			SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+			pahDstSyncHandles = psCCBKick->hDstSyncHandles;
+			for (i=0; i<psCCBKick->ui32NumDstSyncObjects; i++)
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pahDstSyncHandles[i];
+				if (psSyncInfo)
+					psSyncInfo->psSyncData->ui32WriteOpsComplete = psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal+1;
+			}
+		}
+
+		/* Copy status vals over */
+		for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+		{
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
+			/* derive offset into meminfo and write the status value */
+			*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+							+ (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
+							- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#else
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+			psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#endif
+		}
+	}
+#if defined(SUPPORT_DMABUF)
+	PVRLinuxFenceCheckAll();
+#endif
+#endif
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+			KICK_TOKEN_DOKICK);
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	SystraceTAKick(psDevInfo, psCCBKick->ui32FrameNum, psCCBKick->sHWRTDataDevAddr.uiAddr, psCCBKick->bIsFirstKick);
+#endif
+	return eError;
+}
+
+/******************************************************************************
+ End of file (sgxkick.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxpower.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxpower.c
new file mode 100644
index 0000000..75cdd06
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxpower.c
@@ -0,0 +1,666 @@
+/*************************************************************************/ /*!
+@Title          Device specific power routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+extern IMG_UINT32 g_ui32HostIRQCountSample;
+
+#if defined(SUPPORT_HW_RECOVERY)
+static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE		*psDeviceNode,
+								SGX_TIMING_INFORMATION	*psSGXTimingInfo,
+								IMG_HANDLE				*phTimer)
+{
+	/*
+		Install timer callback for HW recovery at 50 times lower
+		frequency than the microkernel timer.
+	*/
+	*phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+						  1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
+	if(*phTimer == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	return PVRSRV_OK;
+}
+#endif /* SUPPORT_HW_RECOVERY*/
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXUpdateTimingInfo
+
+ @Description
+
+ 	Derives the microkernel timing info from the system-supplied values
+
+ @Input	   psDeviceNode : SGX Device node
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE	*psDeviceNode)
+{
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+	SGX_TIMING_INFORMATION	sSGXTimingInfo = {0};
+#else
+	SGX_DEVICE_MAP		*psSGXDeviceMap;
+#endif
+	IMG_UINT32		ui32ActivePowManSampleRate;
+	SGX_TIMING_INFORMATION	*psSGXTimingInfo;
+
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+	psSGXTimingInfo = &sSGXTimingInfo;
+	SysGetSGXTimingInformation(psSGXTimingInfo);
+#else
+	SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+						  (IMG_VOID**)&psSGXDeviceMap);
+	psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+	{
+		PVRSRV_ERROR			eError;
+		IMG_UINT32	ui32OlduKernelFreq;
+
+		if (psDevInfo->hTimer != IMG_NULL)
+		{
+			ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
+			if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
+			{
+				/*
+					The ukernel timer frequency has changed.
+				*/
+				IMG_HANDLE hNewTimer;
+				
+				eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
+				if (eError == PVRSRV_OK)
+				{
+					eError = OSRemoveTimer(psDevInfo->hTimer);
+					if (eError != PVRSRV_OK)
+					{
+						PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer"));
+					}
+					psDevInfo->hTimer = hNewTimer;
+				}
+				else
+				{
+					/* Failed to allocate the new timer, leave the old one. */
+				}
+			}
+		}
+		else
+		{
+			eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+
+		psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+			psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
+	}
+#endif /* SUPPORT_HW_RECOVERY*/
+
+	/* Copy the SGX clock speed for use in the kernel */
+	psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+	psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
+
+	/* FIXME: no need to duplicate - remove it from psDevInfo */
+	psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
+#if defined(PDUMP)
+	PDUMPCOMMENT("Host Control - Microkernel clock");
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+			 offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
+			 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+			 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif /* PDUMP */
+
+	if (psSGXTimingInfo->bEnableActivePM)
+	{
+		ui32ActivePowManSampleRate =
+			psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+		/*
+			ui32ActivePowerCounter has the value 0 when SGX is not idle.
+			When SGX becomes idle, the value of ui32ActivePowerCounter is changed from 0 to ui32ActivePowManSampleRate.
+			The ukernel timer routine decrements the value of ui32ActivePowerCounter if it is not 0.
+			When the ukernel timer decrements ui32ActivePowerCounter from 1 to 0, the ukernel timer will
+				request power down.
+			Therefore the minimum value of ui32ActivePowManSampleRate is 1.
+		*/
+		ui32ActivePowManSampleRate += 1;
+	}
+	else
+	{
+		ui32ActivePowManSampleRate = 0;
+	}
+
+	psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate;
+#if defined(PDUMP)
+	PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+			 offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
+			 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+			 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif /* PDUMP */
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXStartTimer
+
+ @Description
+
+	Start the microkernel timer
+
+ @Input	   psDevInfo : SGX Device Info
+
+ @Return   IMG_VOID :
+
+******************************************************************************/
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO	*psDevInfo)
+{
+	#if defined(SUPPORT_HW_RECOVERY)
+	PVRSRV_ERROR	eError;
+
+	eError = OSEnableTimer(psDevInfo->hTimer);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
+	}
+	#else
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	#endif /* SUPPORT_HW_RECOVERY */
+}
+
+
+#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+/*!
+******************************************************************************
+
+ @Function	SGXPollForClockGating
+
+ @Description
+
+ 	Wait until the SGX core clocks have gated.
+
+ @Input	   psDevInfo : SGX Device Info
+ @Input	   ui32Register : Offset of register to poll
+ @Input	   ui32Register : Value of register to poll for
+ @Input	   pszComment : Description of poll
+
+ @Return   IMG_VOID :
+
+******************************************************************************/
+static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO	*psDevInfo,
+									   IMG_UINT32			ui32Register,
+									   IMG_UINT32			ui32RegisterValue,
+									   IMG_CHAR				*pszComment)
+{
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(ui32Register);
+	PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
+	PVR_UNREFERENCED_PARAMETER(pszComment);
+
+	#if !defined(NO_HARDWARE)
+	PVR_ASSERT(psDevInfo != IMG_NULL);
+
+	/* PRQA S 0505 1 */ /* QAC does not like assert() */
+	if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
+						0,
+						ui32RegisterValue,
+						MAX_HW_TIME_US,
+						MAX_HW_TIME_US/WAIT_TRY_COUNT,
+						IMG_FALSE) != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment));
+		SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+		PVR_DBG_BREAK;
+	}
+	#endif /* NO_HARDWARE */
+
+	PDUMPCOMMENT("%s", pszComment);
+	PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue, PDUMP_POLL_OPERATOR_EQUAL);
+}
+#endif
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXPrePowerState
+
+ @Description
+
+ does necessary preparation before power state transition
+
+ @Input	   hDevHandle : SGX Device Node
+ @Input	   eNewPowerState : New power state
+ @Input	   eCurrentPowerState : Current power state
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE				hDevHandle,
+							   PVRSRV_DEV_POWER_STATE	eNewPowerState,
+							   PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	if ((eNewPowerState != eCurrentPowerState) &&
+		(eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+	{
+		PVRSRV_ERROR		eError;
+		PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+		PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+		IMG_UINT32			ui32PowerCmd, ui32CompleteStatus;
+		SGXMKIF_COMMAND		sCommand = {0};
+#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+		IMG_UINT32			ui32Core;
+		IMG_UINT32			ui32CoresEnabled;
+#endif
+
+		#if defined(SUPPORT_HW_RECOVERY)
+		/* Disable timer callback for HW recovery */
+		eError = OSDisableTimer(psDevInfo->hTimer);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
+			return eError;
+		}
+		#endif /* SUPPORT_HW_RECOVERY */
+
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+		{
+			/* Request the ukernel to idle SGX and save its state. */
+			ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
+			ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
+			PDUMPCOMMENT("SGX power off request");
+		}
+		else
+		{
+			/* Request the ukernel to idle SGX. */
+			ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
+			ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+			PDUMPCOMMENT("SGX idle request");
+		}
+
+		sCommand.ui32Data[1] = ui32PowerCmd;
+
+		eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command"));
+			return eError;
+		}
+
+		/* Wait for the ukernel to complete processing. */
+		#if !defined(NO_HARDWARE)
+		if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
+							ui32CompleteStatus,
+							ui32CompleteStatus,
+							MAX_HW_TIME_US,
+							MAX_HW_TIME_US/WAIT_TRY_COUNT,
+							IMG_FALSE) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+			SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+			PVR_DBG_BREAK;
+		}
+		#endif /* NO_HARDWARE */
+
+		if (psDevInfo->bSGXIdle == IMG_FALSE)
+		{
+			psDevInfo->bSGXIdle = IMG_TRUE;
+			SysSGXIdleEntered();
+		}
+
+		#if defined(PDUMP)
+		PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
+		PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+					offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+					ui32CompleteStatus,
+					ui32CompleteStatus,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					0,
+					MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+		#endif /* PDUMP */
+
+		/* Wait for the pending ukernel to host interrupts to come back. */
+		#if !defined(NO_HARDWARE) && defined(SUPPORT_LISR_MISR_SYNC)
+		if (PollForValueKM(&g_ui32HostIRQCountSample,
+							psDevInfo->psSGXHostCtl->ui32InterruptCount,
+							0xffffffff,
+							MAX_HW_TIME_US,
+							MAX_HW_TIME_US/WAIT_TRY_COUNT,
+							IMG_FALSE) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for pending interrupts failed."));
+			SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+			PVR_DBG_BREAK;
+		}
+		#endif /* NO_HARDWARE && SUPPORT_LISR_MISR_SYNC*/
+		
+#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+		if(psDevInfo->bDisableClockGating == IMG_FALSE)
+		{
+#if defined(SGX_FEATURE_MP)
+			ui32CoresEnabled = ((OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE) & EUR_CR_MASTER_CORE_ENABLE_MASK) >> EUR_CR_MASTER_CORE_ENABLE_SHIFT) + 1;
+#else
+			ui32CoresEnabled = 1;
+#endif
+
+			for (ui32Core = 0; ui32Core < ui32CoresEnabled; ui32Core++)
+			{
+				/* Wait for SGX clock gating. */
+				SGXPollForClockGating(psDevInfo,
+									SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
+									psDevInfo->ui32ClkGateStatusMask,
+									"Wait for SGX clock gating");
+			}
+
+#if defined(SGX_FEATURE_MP)
+			/* Wait for SGX master clock gating. */
+			SGXPollForClockGating(psDevInfo,
+								psDevInfo->ui32MasterClkGateStatusReg,
+								psDevInfo->ui32MasterClkGateStatusMask,
+								"Wait for SGX master clock gating");
+
+			SGXPollForClockGating(psDevInfo,
+								psDevInfo->ui32MasterClkGateStatus2Reg,
+								psDevInfo->ui32MasterClkGateStatus2Mask,
+								"Wait for SGX master clock gating (2)");
+#endif /* SGX_FEATURE_MP */
+		}
+#endif /* defined(SGX_FEATURE_AUTOCLOCKGATING) */
+
+		if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+		{
+			/* Finally, de-initialise some registers. */
+			eError = SGXDeinitialise(psDevInfo);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %u", eError));
+				return eError;
+			}
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXPostPowerState
+
+ @Description
+
+ does necessary preparation after power state transition
+
+ @Input	   hDevHandle : SGX Device Node
+ @Input	   eNewPowerState : New power state
+ @Input	   eCurrentPowerState : Current power state
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE				hDevHandle,
+								PVRSRV_DEV_POWER_STATE	eNewPowerState,
+								PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	if ((eNewPowerState != eCurrentPowerState) &&
+		(eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+	{
+		PVRSRV_ERROR		eError;
+		PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+		PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+		SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+		/* Reset the power manager flags. */
+		psSGXHostCtl->ui32PowerStatus = 0;
+		#if defined(PDUMP)
+		PDUMPCOMMENT("Host Control - Reset power status");
+		PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+				 offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+				 sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+				 MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+		#endif /* PDUMP */
+
+		if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+		{
+			/*
+				Coming up from off, re-initialise SGX.
+			*/
+
+			/*
+				Re-generate the timing data required by SGX.
+			*/
+			eError = SGXUpdateTimingInfo(psDeviceNode);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+				return eError;
+			}
+
+			/*
+				Run the SGX init script.
+			*/
+			eError = SGXInitialise(psDevInfo, IMG_FALSE);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed"));
+				return eError;
+			}
+		}
+		else
+		{
+			/*
+				Coming up from idle, restart the ukernel.
+			*/
+			SGXMKIF_COMMAND		sCommand = {0};
+
+			sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
+			eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0, IMG_NULL, IMG_FALSE);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %u", eError));
+				return eError;
+			}
+		}
+
+		SGXStartTimer(psDevInfo);
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXPreClockSpeedChange
+
+ @Description
+
+	Does processing required before an SGX clock speed change.
+
+ @Input	   hDevHandle : SGX Device Node
+ @Input	   bIdleDevice : Whether the microkernel needs to be idled
+ @Input	   eCurrentPowerState : Power state of the device
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE				hDevHandle,
+									 IMG_BOOL				bIdleDevice,
+									 PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	PVRSRV_ERROR		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+	if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+	{
+		if (bIdleDevice)
+		{
+			/*
+			 * Idle SGX.
+			 */
+			PDUMPSUSPEND();
+
+			eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
+									  PVRSRV_DEV_POWER_STATE_ON);
+
+			if (eError != PVRSRV_OK)
+			{
+				PDUMPRESUME();
+				return eError;
+			}
+		}
+		else
+		{
+			#if defined(SUPPORT_HW_RECOVERY)
+			PVRSRV_ERROR	eError;
+
+			eError = OSDisableTimer(psDevInfo->hTimer);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
+			}
+			#endif /* SUPPORT_HW_RECOVERY */
+		}
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %uHz",
+			psDevInfo->ui32CoreClockSpeed));
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXPostClockSpeedChange
+
+ @Description
+
+	Does processing required after an SGX clock speed change.
+
+ @Input	   hDevHandle : SGX Device Node
+ @Input	   bIdleDevice : Whether the microkernel had been idled previously
+ @Input	   eCurrentPowerState : Power state of the device
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE				hDevHandle,
+									  IMG_BOOL					bIdleDevice,
+									  PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	PVRSRV_DEVICE_NODE	*psDeviceNode = hDevHandle;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	IMG_UINT32			ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
+
+	PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
+
+	if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+	{
+		PVRSRV_ERROR eError;
+
+		/*
+			Re-generate the timing data required by SGX.
+		*/
+		eError = SGXUpdateTimingInfo(psDeviceNode);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+			return eError;
+		}
+
+		if (bIdleDevice)
+		{
+			/*
+			 * Resume SGX.
+			 */
+			eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
+									   PVRSRV_DEV_POWER_STATE_IDLE);
+
+			PDUMPRESUME();
+
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+		else
+		{
+			SGXStartTimer(psDevInfo);
+		}
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %uHz to %uHz",
+			ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
+
+	return PVRSRV_OK;
+}
+
+
+/******************************************************************************
+ End of file (sgxpower.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxreset.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxreset.c
new file mode 100644
index 0000000..ecf0e62
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxreset.c
@@ -0,0 +1,824 @@
+/*************************************************************************/ /*!
+@Title          Device specific reset routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+#include "sgxutils.h"
+
+#include "pdump_km.h"
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXInitClocks
+
+ @Description
+	Initialise the SGX clocks
+
+ @Input psDevInfo - device info. structure
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO	*psDevInfo,
+					   IMG_UINT32			ui32PDUMPFlags)
+{
+	IMG_UINT32	ui32RegVal;
+	
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif /* PDUMP */
+	
+	ui32RegVal = psDevInfo->ui32ClkGateCtl;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_CLKGATECTL, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(EUR_CR_CLKGATECTL2)
+	ui32RegVal = psDevInfo->ui32ClkGateCtl2;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL2, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_CLKGATECTL2, ui32RegVal, ui32PDUMPFlags);
+#endif
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXResetInitBIFContexts
+
+ @Description
+	Initialise the BIF memory contexts
+
+ @Input psDevInfo - SGX Device Info
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+static IMG_VOID SGXResetInitBIFContexts(PVRSRV_SGXDEV_INFO	*psDevInfo,
+										IMG_UINT32			ui32PDUMPFlags)
+{
+	IMG_UINT32	ui32RegVal;
+
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif /* PDUMP */
+
+	ui32RegVal = 0;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the BIF bank settings\r\n");
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the BIF directory list\r\n");
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	{
+		IMG_UINT32	ui32DirList, ui32DirListReg;
+
+		for (ui32DirList = 1;
+			 ui32DirList < SGX_FEATURE_BIF_NUM_DIRLISTS;
+			 ui32DirList++)
+		{
+			ui32DirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (ui32DirList - 1);
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32DirListReg, ui32RegVal);
+			PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
+		}
+	}
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXResetSetupBIFContexts
+
+ @Description
+	Configure the BIF for the EDM context
+
+ @Input psDevInfo - SGX Device Info
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+static IMG_VOID SGXResetSetupBIFContexts(PVRSRV_SGXDEV_INFO	*psDevInfo,
+										 IMG_UINT32			ui32PDUMPFlags)
+{
+	IMG_UINT32	ui32RegVal;
+
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif /* PDUMP */
+	
+	#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	/* Set up EDM for bank 0 to point at kernel context */
+	ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
+
+	#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+	/* Set up 2D core for bank 0 to point at kernel context */
+	ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
+	#endif /* SGX_FEATURE_2D_HARDWARE */
+
+	#if defined(FIX_HW_BRN_23410)
+	/* Set up TA core for bank 0 to point at kernel context to guarantee it is a valid context */
+	ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
+	#endif /* FIX_HW_BRN_23410 */
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Set up EDM requestor page table in BIF\r\n");
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+	#endif /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) */
+
+	{
+		IMG_UINT32	ui32EDMDirListReg;
+
+		/* Set up EDM context with kernel page directory */
+		#if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
+		ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
+		#else
+		/* Bases 0 and 1 are not necessarily contiguous */
+		ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
+		#endif /* SGX_BIF_DIR_LIST_INDEX_EDM */
+
+		ui32RegVal = (IMG_UINT32)(psDevInfo->sKernelPDDevPAddr.uiAddr >> SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+		
+#if defined(FIX_HW_BRN_28011)
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+		PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+#endif
+
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg, ui32RegVal);
+		PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the EDM's directory list base\r\n");
+		PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, ui32EDMDirListReg, ui32RegVal, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+	}
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXResetSleep
+
+ @Description
+
+ Sleep for a short time to allow reset register writes to complete.
+ Required because no status registers are available to poll on.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+ @Input bPDump - Pdump the sleep
+
+ @Return   Nothing
+
+******************************************************************************/
+static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							  IMG_UINT32			ui32PDUMPFlags,
+							  IMG_BOOL				bPDump)
+{
+#if defined(PDUMP) || defined(EMULATOR)
+	IMG_UINT32	ui32ReadRegister;
+
+	#if defined(SGX_FEATURE_MP)
+	ui32ReadRegister = EUR_CR_MASTER_SOFT_RESET;
+	#else
+	ui32ReadRegister = EUR_CR_SOFT_RESET;
+	#endif /* SGX_FEATURE_MP */
+#endif
+
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif /* PDUMP */
+
+	/* Sleep for 100 SGX clocks */
+	SGXWaitClocks(psDevInfo, 100);
+	if (bPDump)
+	{
+		PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+		PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Read back to flush the register writes\r\n");
+		PDumpRegRead(SGX_PDUMPREG_NAME, ui32ReadRegister, ui32PDUMPFlags);
+#endif
+	}
+
+#if defined(EMULATOR)
+	/*
+		Read a register to make sure we wait long enough on the emulator...
+	*/
+	OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32ReadRegister);
+#endif
+}
+
+
+#if !defined(SGX_FEATURE_MP)
+/*!
+*******************************************************************************
+
+ @Function	SGXResetSoftReset
+
+ @Description
+
+ Write to the SGX soft reset register.
+
+ @Input psDevInfo - SGX Device Info
+ @Input bResetBIF - Include the BIF in the soft reset
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+ @Input bPDump - Pdump the sleep
+
+ @Return   Nothing
+
+******************************************************************************/
+static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO	*psDevInfo,
+								  IMG_BOOL				bResetBIF,
+								  IMG_UINT32			ui32PDUMPFlags,
+								  IMG_BOOL				bPDump)
+{
+	IMG_UINT32 ui32SoftResetRegVal;
+
+	ui32SoftResetRegVal =
+					/* add common reset bits: */
+					EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+					EUR_CR_SOFT_RESET_TA_RESET_MASK  |
+					EUR_CR_SOFT_RESET_USE_RESET_MASK |
+					EUR_CR_SOFT_RESET_ISP_RESET_MASK |
+					EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+
+/* add conditional reset bits: */
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TE_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MTE_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MTE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ISP2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ISP2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PDS_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PDS_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PBE_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PBE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MADD_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MADD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ITR_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ITR_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TEX_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TEX_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_VDM_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_VDM_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK)
+	ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK;
+#endif
+
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif /* PDUMP */
+
+	if (bResetBIF)
+	{
+		ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
+	}
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32SoftResetRegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+	}
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXResetInvalDC
+
+ @Description
+
+ Invalidate the BIF Directory Cache and wait for the operation to complete.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return   Nothing
+
+******************************************************************************/
+static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							    IMG_UINT32			ui32PDUMPFlags,
+								IMG_BOOL			bPDump)
+{
+	IMG_UINT32 ui32RegVal;
+
+	/* Invalidate BIF Directory cache. */
+#if defined(EUR_CR_BIF_CTRL_INVAL)
+	ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL_INVAL, ui32RegVal, ui32PDUMPFlags);
+	}
+#else
+	ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+	}
+
+	ui32RegVal = 0;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	if (bPDump)
+	{
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+	}
+#endif
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+	{
+		/*
+			Wait for the DC invalidate to complete - indicated by
+			outstanding reads reaching zero.
+		*/
+		if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+							0,
+							EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+							MAX_HW_TIME_US,
+							MAX_HW_TIME_US/WAIT_TRY_COUNT,
+							IMG_FALSE) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"Wait for DC invalidate failed."));
+			PVR_DBG_BREAK;
+		}
+
+		if (bPDump)
+		{
+			PDUMPREGPOLWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags, PDUMP_POLL_OPERATOR_EQUAL);
+		}
+	}
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
+}
+#endif /* SGX_FEATURE_MP */
+
+
+/*!
+*******************************************************************************
+
+ @Function	SGXReset
+
+ @Description
+
+ Reset chip
+
+ @Input psDevInfo - device info. structure
+ @Input bHardwareRecovery - true if recovering powered hardware,
+ 							false if powering up
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO	*psDevInfo,
+				  IMG_BOOL				bHardwareRecovery,
+				  IMG_UINT32			ui32PDUMPFlags)
+#if !defined(SGX_FEATURE_MP)
+{
+	IMG_UINT32 ui32RegVal;
+#if defined(EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK)
+	const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK;
+#else
+	const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+#endif
+
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif /* PDUMP */
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
+
+#if defined(FIX_HW_BRN_23944)
+	/* Pause the BIF. */
+	ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+	if (ui32RegVal & ui32BifFaultMask)
+	{
+		/* Page fault needs to be cleared before resetting the BIF. */
+		ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+		ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+	}
+#endif /* defined(FIX_HW_BRN_23944) */
+
+	/* Reset all including BIF */
+	SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	/*
+		Initialise the BIF state.
+	*/
+#if defined(SGX_FEATURE_36BIT_MMU)
+	/* enable 36bit addressing mode if the MMU supports it*/
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
+#else
+	#if defined(EUR_CR_BIF_36BIT_ADDRESSING)
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, 
+				EUR_CR_BIF_36BIT_ADDRESSING, 
+				0);
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, 
+				EUR_CR_BIF_36BIT_ADDRESSING, 
+				0, 
+				ui32PDUMPFlags);
+	#endif
+#endif
+
+	SGXResetInitBIFContexts(psDevInfo, ui32PDUMPFlags);
+
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+	/*
+		Initialise the memory arbiter to its default state
+	*/
+	ui32RegVal	= (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
+				  (7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
+				  (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
+#endif /* EUR_CR_BIF_MEM_ARB_CONFIG */
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	#if defined(SGX_BYPASS_SYSTEM_CACHE)
+		/* set the SLC to bypass all accesses */
+		ui32RegVal = MNE_CR_CTRL_BYPASS_ALL_MASK;
+	#else
+		#if defined(FIX_HW_BRN_26620)
+			ui32RegVal = 0;
+		#else
+			/* set the SLC to bypass cache-coherent accesses */
+			ui32RegVal = MNE_CR_CTRL_BYP_CC_MASK;
+		#endif
+		#if defined(FIX_HW_BRN_34028)
+			/* Bypass the MNE for the USEC requester */
+			ui32RegVal |= (8 << MNE_CR_CTRL_BYPASS_SHIFT);
+		#endif
+	#endif /* SGX_BYPASS_SYSTEM_CACHE */
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, MNE_CR_CTRL, ui32RegVal);
+	PDUMPREG(SGX_PDUMPREG_NAME, MNE_CR_CTRL, ui32RegVal);
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+	if (bHardwareRecovery)
+	{
+		/*
+			Set all requestors to the dummy PD which forces all memory
+			accesses to page fault.
+			This enables us to flush out BIF requests from parts of SGX
+			which do not have their own soft reset.
+			Note: sBIFResetPDDevPAddr.uiAddr is a relative address (2GB max)
+			MSB is the bus master flag; 1 == enabled
+		*/
+		ui32RegVal = (IMG_UINT32)psDevInfo->sBIFResetPDDevPAddr.uiAddr;
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+		/* Bring BIF out of reset. */
+		SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+		SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+		/*
+			Check for a page fault from parts of SGX which do not have a reset.
+		*/
+		for (;;)
+		{
+			IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+			IMG_DEV_VIRTADDR sBifFault;
+			IMG_UINT32 ui32PDIndex, ui32PTIndex;
+
+			if ((ui32BifIntStat & ui32BifFaultMask) == 0)
+			{
+				break;
+			}
+
+			/*
+				There is a page fault, so reset the BIF again, map in the dummy page,
+				bring the BIF up and invalidate the Directory Cache.
+			*/
+			sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+			PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr));
+			ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+			ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+			/* Put the BIF into reset. */
+			SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
+
+			/* Map in the dummy page. */
+			psDevInfo->pui32BIFResetPD[ui32PDIndex] = (IMG_UINT32)(psDevInfo->sBIFResetPTDevPAddr.uiAddr
+													>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+													| SGX_MMU_PDE_PAGE_SIZE_4K
+													| SGX_MMU_PDE_VALID;
+			psDevInfo->pui32BIFResetPT[ui32PTIndex] = (IMG_UINT32)(psDevInfo->sBIFResetPageDevPAddr.uiAddr
+													>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+													| SGX_MMU_PTE_VALID;
+
+			/* Clear outstanding events. */
+			ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal);
+			ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32RegVal);
+
+			SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+			/* Bring the BIF out of reset. */
+			SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
+			SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+			/* Invalidate Directory Cache. */
+			SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+			/* Unmap the dummy page and try again. */
+			psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
+			psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
+		}
+	}
+	else
+	{
+		/* Bring BIF out of reset. */
+		SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+		SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+	}	
+
+	/*
+		Initialise the BIF memory contexts before bringing the rest of SGX out of reset.
+	*/
+	SGXResetSetupBIFContexts(psDevInfo, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+	/* check that the heap base has the right alignment (1Mb) */
+	#if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
+		#error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
+	#endif
+	/* Set up 2D requestor base */
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
+#endif
+
+#if defined(SGX_FEATURE_ADDRESS_SPACE_EXTENSION)
+	/*TODO: Set up USEC requestor base, here its set to ZERO (hard-coded) */
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_USEC_REQ_BASE, 0);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_USEC_REQ_BASE, 0, ui32PDUMPFlags);
+#endif
+
+	/* Invalidate BIF Directory cache. */
+	SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
+
+	/* Take chip out of reset */
+	ui32RegVal = 0;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+	/* wait a bit */
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
+
+#else
+
+{
+	IMG_UINT32 ui32RegVal;
+	
+	PVR_UNREFERENCED_PARAMETER(bHardwareRecovery);
+
+#if !defined(PDUMP)
+	PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif /* PDUMP */
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX MP reset sequence\r\n");
+
+	/* Put hydra into soft reset */
+	ui32RegVal = EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK  |
+				 EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK  |
+				 EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK  |
+				 EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+
+	if (bHardwareRecovery)
+	{
+		ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK;
+	}
+
+#if defined(SGX_FEATURE_PTLA)
+	ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK;
+#endif
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
+#endif
+
+	/* Hard reset the slave cores */
+	ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(0)  |
+				  EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(1)  |
+				  EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(2)  |
+				  EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(3);
+
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Soft reset hydra partition, hard reset the cores\r\n");
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	ui32RegVal = 0;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_CTRL, ui32RegVal);
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra BIF control\r\n");
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	#if defined(SGX_BYPASS_SYSTEM_CACHE)
+		ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_MASK;
+	#else
+		ui32RegVal = EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK |
+		#if defined(FIX_HW_BRN_30954)
+						EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK |
+		#endif
+		#if defined(PVR_SLC_8KB_ADDRESS_MODE)
+						(4 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
+		#endif
+		#if defined(FIX_HW_BRN_33809)
+			(1 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
+		#endif
+						(0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+		PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra SLC control\r\n");
+		PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+
+		ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK;
+	#if defined(FIX_HW_BRN_31620)
+		ui32RegVal |= EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_MMU_MASK;
+	#endif
+	#if defined(FIX_HW_BRN_31195)
+		ui32RegVal |= EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_MASK |
+				EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_MASK |
+				EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_MASK |
+				EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK |
+				EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK;
+	#endif
+	#endif /* SGX_BYPASS_SYSTEM_CACHE */
+		OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+		PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra SLC bypass control\r\n");
+		PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	/* Remove the resets */
+	ui32RegVal = 0;
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Remove the resets from all of SGX\r\n");
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+	
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Turn on the slave cores' clock gating\r\n");
+	SGXInitClocks(psDevInfo, ui32PDUMPFlags);
+
+	SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the slave BIFs\r\n");
+
+#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_31620) || defined(FIX_HW_BRN_31671) || defined(FIX_HW_BRN_32085)
+	#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
+	/* disable prefetch */
+	ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
+	#else
+	ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_MASK; 
+	#endif
+	#if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
+	/* enable the DC TLB */
+	ui32RegVal |= EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
+	#endif
+
+	/* Master bank */
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal);
+	PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+	#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
+	/* disable prefetch */
+	ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
+	#else
+	ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK; 
+	#endif
+	#if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
+	/* enable the DC TLB */
+	ui32RegVal |= EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
+	#endif
+
+	/* Per-core */
+	{
+		IMG_UINT32 ui32Core;
+
+		for (ui32Core=0;ui32Core<SGX_FEATURE_MP_CORE_COUNT;ui32Core++)
+		{
+			OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BIF_MMU_CTRL, ui32Core), ui32RegVal);
+			PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_BIF_MMU_CTRL, ui32Core), ui32RegVal, ui32PDUMPFlags);
+		}
+	}
+#endif
+
+	SGXResetInitBIFContexts(psDevInfo, ui32PDUMPFlags);
+	SGXResetSetupBIFContexts(psDevInfo, ui32PDUMPFlags);
+	
+	PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX MP reset sequence\r\n");
+}	
+#endif /* SGX_FEATURE_MP */
+
+
+/******************************************************************************
+ End of file (sgxreset.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxtransfer.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
new file mode 100644
index 0000000..a13630b
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxtransfer.c
@@ -0,0 +1,1007 @@
+/*************************************************************************/ /*!
+@Title          Device specific transfer queue routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if defined(TRANSFER_QUEUE)
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include "pvr_sync_common.h"
+#endif
+
+#if defined(SUPPORT_DMABUF)
+#include "pvr_linux_fence.h"
+#endif
+
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick)
+{
+	PVRSRV_KERNEL_MEM_INFO		*psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+	SGXMKIF_COMMAND				sCommand = {0};
+	SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+	PVRSRV_KERNEL_SYNC_INFO 	*psSyncInfo;
+	PVRSRV_ERROR				eError;
+	IMG_UINT32					loop;
+	IMG_HANDLE					hDevMemContext = IMG_NULL;
+	IMG_BOOL					abSrcSyncEnable[SGX_MAX_TRANSFER_SYNC_OPS];
+	IMG_UINT32					ui32RealSrcSyncNum = 0;
+	IMG_BOOL					abDstSyncEnable[SGX_MAX_TRANSFER_SYNC_OPS];
+	IMG_UINT32					ui32RealDstSyncNum = 0;
+
+#if defined(SUPPORT_DMABUF)
+	IMG_UINT32			ui32FenceTag = 0;
+	IMG_UINT32			ui32NumResvObjs = 0;
+	IMG_BOOL			bBlockingFences = IMG_FALSE;
+#endif
+
+
+#if defined(FIX_HW_BRN_31620)
+	hDevMemContext = psKick->hDevMemContext;
+#endif
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_ENTER, TRANSFER_TOKEN_SUBMIT);
+
+	for (loop = 0; loop < SGX_MAX_TRANSFER_SYNC_OPS; loop++)
+	{
+		abSrcSyncEnable[loop] = IMG_TRUE;
+		abDstSyncEnable[loop] = IMG_TRUE;
+	}
+
+	if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset"));
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+				TRANSFER_TOKEN_SUBMIT);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	/* override QAC warning about stricter alignment */
+	/* PRQA S 3305 1 */
+	psSharedTransferCmd =  CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_START, TRANSFER_TOKEN_SUBMIT);
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CCB,
+			TRANSFER_TOKEN_CCB_OFFSET, psKick->ui32SharedCmdCCBOffset);
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_TA_SYNC,
+					  psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+		psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_3D);
+		psSharedTransferCmd->ui32TASyncReadOpsPendingVal  = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+	else
+	{
+		psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+		psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_3D_SYNC,
+					  psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+		psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = SyncTakeWriteOp(psSyncInfo,SYNC_OP_CLASS_TQ_3D);
+		psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+	else
+	{
+		psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+		psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+	}
+
+	/* filter out multiple occurrences of the same sync object from srcs or dests
+	 * note : the same sync can still be used to synchronize both src and dst.
+	 */
+	for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumSrcSync); loop++)
+	{
+		IMG_UINT32 i;
+
+		PVRSRV_KERNEL_SYNC_INFO * psMySyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+	
+		for (i = 0; i < loop; i++)	
+		{
+			if (abSrcSyncEnable[i])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+
+				if (psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr == psMySyncInfo->sWriteOpsCompleteDevVAddr.uiAddr)
+				{
+					PVR_DPF((PVR_DBG_WARNING, "SGXSubmitTransferKM : Same src synchronized multiple times!"));
+					abSrcSyncEnable[loop] = IMG_FALSE;
+					break;
+				}
+			}
+		}
+		if (abSrcSyncEnable[loop])
+		{
+			ui32RealSrcSyncNum++;
+		}
+	}
+	for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumDstSync); loop++)
+	{
+		IMG_UINT32 i;
+
+		PVRSRV_KERNEL_SYNC_INFO * psMySyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+	
+		for (i = 0; i < loop; i++)	
+		{
+			if (abDstSyncEnable[i])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i];
+
+				if (psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr == psMySyncInfo->sWriteOpsCompleteDevVAddr.uiAddr)
+				{
+					PVR_DPF((PVR_DBG_WARNING, "SGXSubmitTransferKM : Same dst synchronized multiple times!"));
+					abDstSyncEnable[loop] = IMG_FALSE;
+					break;
+				}
+			}
+		}
+		if (abDstSyncEnable[loop])
+		{
+			ui32RealDstSyncNum++;
+		}
+	}
+
+	if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+	{
+		IMG_UINT32 i = 0;
+
+#if defined(SUPPORT_DMABUF)
+		ui32NumResvObjs = PVRLinuxFenceNumResvObjs(&bBlockingFences,
+					psKick->ui32NumSrcSync,
+					psKick->ahSrcSyncInfo,
+					abSrcSyncEnable,
+					psKick->ui32NumDstSync,
+					psKick->ahDstSyncInfo,
+					abDstSyncEnable);
+		/*
+		 * If there are no blocking fences, the GPU need not wait
+		 * whilst the reservation objects are being processed. They
+		 * can be processed later, after the kick.
+		 */
+		if (ui32NumResvObjs && bBlockingFences)
+		{
+			eError = PVRLinuxFenceProcess(&ui32FenceTag,
+					ui32NumResvObjs,
+					bBlockingFences,
+					psKick->ui32NumSrcSync,
+					psKick->ahSrcSyncInfo,
+					abSrcSyncEnable,
+					psKick->ui32NumDstSync,
+					psKick->ahDstSyncInfo,
+					abDstSyncEnable);
+			if (eError != PVRSRV_OK)
+			{
+				return eError;
+			}
+		}
+#endif
+		for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+		{
+			if (abSrcSyncEnable[loop])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+
+				PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_SRC_SYNC,
+						psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+				psSharedTransferCmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+				psSharedTransferCmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+				psSharedTransferCmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr; 
+				psSharedTransferCmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+				i++;
+			}
+		}
+		PVR_ASSERT(i == ui32RealSrcSyncNum);
+
+		i = 0;
+		for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+		{
+			if (abDstSyncEnable[loop])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+
+				psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
+
+				PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_DST_SYNC,
+						psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+				psSharedTransferCmd->asDstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+				psSharedTransferCmd->asDstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+				psSharedTransferCmd->asDstSyncs[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+				psSharedTransferCmd->asDstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+				psSharedTransferCmd->asDstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+				psSharedTransferCmd->asDstSyncs[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+				i++;
+			}
+		}
+		PVR_ASSERT(i == ui32RealDstSyncNum);
+
+		/*
+		 * We allow source and destination sync objects to be the
+		 * same, which is why the read/write pending updates are delayed
+		 * until the transfer command has been updated with the current
+		 * values from the objects.
+		 */
+		for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+		{
+			if (abSrcSyncEnable[loop])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+				SyncTakeReadOp(psSyncInfo, SYNC_OP_CLASS_TQ_3D);
+			}
+		}
+		for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+		{
+			if (abDstSyncEnable[loop])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+				SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_3D);
+			}
+		}
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+		if (ui32RealDstSyncNum <= (SGX_MAX_DST_SYNCS_TQ - 1) && psKick->iFenceFd > 0)
+		{
+			IMG_HANDLE ahSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+			PVRSRV_DEVICE_SYNC_OBJECT *apsDevSyncs = &psSharedTransferCmd->asDstSyncs[ui32RealDstSyncNum];
+			IMG_UINT32 ui32NumSrcSyncs = 1;
+			IMG_UINT32 i;
+			ahSyncInfo[0] = (IMG_HANDLE)(uintptr_t)(psKick->iFenceFd - 1);
+
+			eError = PVRSyncPatchTransferSyncInfos(ahSyncInfo, apsDevSyncs, &ui32NumSrcSyncs);
+			if (eError != PVRSRV_OK)
+			{
+				/* We didn't kick yet, or perform PDUMP processing, so we should
+				 * be able to trivially roll back any changes made to the sync
+				 * data. If we don't do this, we'll wedge services cleanup.
+				 */
+
+				for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+				{
+					if (abDstSyncEnable[loop])
+					{
+						psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+						psSyncInfo->psSyncData->ui32WriteOpsPending--;
+					}
+				}
+
+				for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+				{
+					if (abSrcSyncEnable[loop])
+					{
+						psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+						psSyncInfo->psSyncData->ui32ReadOpsPending--;
+					}
+				}
+
+				if (psKick->h3DSyncInfo != IMG_NULL)
+				{
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+					psSyncInfo->psSyncData->ui32WriteOpsPending++;
+				}
+
+				if (psKick->hTASyncInfo != IMG_NULL)
+				{
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+					psSyncInfo->psSyncData->ui32WriteOpsPending--;
+				}
+
+				PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: PVRSyncPatchTransferKickSyncInfos failed."));
+				PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+						   TRANSFER_TOKEN_SUBMIT);
+				return eError;
+			}
+
+			/* Find a free dst sync to slot in our extra sync */
+			for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+			{
+				if (abDstSyncEnable[loop])
+					break;
+			}
+
+			/* We shouldn't be in this code path if ui32RealDstSyncNum
+			 * didn't allow for at least two free synchronization slots.
+			 */
+			PVR_ASSERT(loop + ui32NumSrcSyncs <= SGX_MAX_TRANSFER_SYNC_OPS);
+
+			/* Slot in the extra dst syncs */
+			for (i = 0; i < ui32NumSrcSyncs; i++)
+			{
+				psKick->ahDstSyncInfo[loop + i] = ahSyncInfo[i];
+				abDstSyncEnable[loop + i] = IMG_TRUE;
+				psKick->ui32NumDstSync++;
+				ui32RealDstSyncNum++;
+			}
+		}
+#endif /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) */
+	}
+
+	psSharedTransferCmd->ui32NumSrcSyncs = ui32RealSrcSyncNum; 
+	psSharedTransferCmd->ui32NumDstSyncs = ui32RealDstSyncNum; 
+
+#if defined(PDUMP)
+	if (PDumpWillCapture(psKick->ui32PDumpFlags))
+	{
+		PDUMPCOMMENT("Shared part of transfer command\r\n");
+		PDUMPMEM(psSharedTransferCmd,
+				psCCBMemInfo,
+				psKick->ui32CCBDumpWOff,
+				sizeof(SGXMKIF_TRANSFERCMD_SHARED),
+				psKick->ui32PDumpFlags,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+		if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+		{
+			IMG_UINT32 i = 0;
+
+			for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+			{
+				if (abSrcSyncEnable[loop])
+				{
+					IMG_UINT32 ui32PDumpReadOp2 = 0;
+					psSyncInfo = psKick->ahSrcSyncInfo[loop];
+
+					PDUMPCOMMENT("Tweak src surface write op in transfer cmd\r\n");
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+					PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT, "TQ Src: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+											psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+											psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+							psCCBMemInfo,
+							psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
+							sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+							psKick->ui32PDumpFlags,
+							MAKEUNIQUETAG(psCCBMemInfo));
+
+					PDUMPCOMMENT("Tweak src surface read op in transfer cmd\r\n");
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+							psCCBMemInfo,
+							psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
+							sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+							psKick->ui32PDumpFlags,
+							MAKEUNIQUETAG(psCCBMemInfo));
+
+					PDUMPCOMMENT("Tweak srv surface read op2 in transfer cmd\r\n");
+					PDUMPMEM(&ui32PDumpReadOp2,
+							psCCBMemInfo,
+							psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal)),
+							sizeof(ui32PDumpReadOp2),
+							psKick->ui32PDumpFlags,
+							MAKEUNIQUETAG(psCCBMemInfo));
+					i++;
+				}
+			}
+
+			i = 0;
+			for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+			{
+				if (abDstSyncEnable[i])
+				{
+					IMG_UINT32 ui32PDumpReadOp2 = 0;
+					psSyncInfo = psKick->ahDstSyncInfo[loop];
+
+					PDUMPCOMMENT("Tweak dest surface write op in transfer cmd\r\n");
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+					PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT, "TQ Dst: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+											psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+											psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+							psCCBMemInfo,
+							psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
+							sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+							psKick->ui32PDumpFlags,
+							MAKEUNIQUETAG(psCCBMemInfo));
+
+					PDUMPCOMMENT("Tweak dest surface read op in transfer cmd\r\n");
+					PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+							psCCBMemInfo,
+							psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
+							sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+							psKick->ui32PDumpFlags,
+							MAKEUNIQUETAG(psCCBMemInfo));
+
+					PDUMPCOMMENT("Tweak dest surface read op2 in transfer cmd\r\n");
+					PDUMPMEM(&ui32PDumpReadOp2,
+							psCCBMemInfo,
+							psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal)),
+							sizeof(ui32PDumpReadOp2),
+							psKick->ui32PDumpFlags,
+							MAKEUNIQUETAG(psCCBMemInfo));
+					i++;
+				}
+			}
+
+			/*
+			 * We allow the first source and destination sync objects to be the
+			 * same, which is why the read/write pending updates are delayed
+			 * until the transfer command has been updated with the current
+			 * values from the objects.
+			 */
+			for (loop = 0; loop < (psKick->ui32NumSrcSync); loop++)
+			{
+				if (abSrcSyncEnable[loop])
+				{	
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+					psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+					PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT,
+											"TQ Src: PDump sync update: uiAddr = 0x%08x, ui32LastReadOpDumpVal = 0x%08x\r\n",
+											psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+											psSyncInfo->psSyncData->ui32LastReadOpDumpVal);
+#endif
+				}
+			}
+
+			for (loop = 0; loop < (psKick->ui32NumDstSync); loop++)
+			{
+				if (abDstSyncEnable[loop])
+				{
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+					psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+					PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT,
+											"TQ Dst: PDump sync update: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+											psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+											psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+				}
+			}
+		}
+
+		if (psKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = psKick->hTASyncInfo;
+
+			PDUMPCOMMENT("Tweak TA/TQ surface write op in transfer cmd\r\n");
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENT("TQ TA/TQ: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32TASyncWriteOpsPendingVal)),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Tweak TA/TQ surface read op in transfer cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui32TASyncReadOpsPendingVal)),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+		}
+
+		if (psKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = psKick->h3DSyncInfo;
+
+			PDUMPCOMMENT("Tweak 3D/TQ surface write op in transfer cmd\r\n");
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENT("TQ 3D/TQ: PDump sync sample: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui323DSyncWriteOpsPendingVal)),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Tweak 3D/TQ surface read op in transfer cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, ui323DSyncReadOpsPendingVal)),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+		}
+	}
+#endif
+
+	sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+	
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_END,
+			TRANSFER_TOKEN_SUBMIT);
+
+	eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags, hDevMemContext, IMG_FALSE);
+
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		/* Client will retry, so undo the sync ops pending increment(s) done above. */
+		if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+		{
+#if defined(SUPPORT_DMABUF)
+				if (ui32NumResvObjs && bBlockingFences)
+				{
+					PVRLinuxFenceRelease(ui32FenceTag,
+						psKick->ui32NumSrcSync,
+						psKick->ahSrcSyncInfo,
+						abSrcSyncEnable,
+						psKick->ui32NumDstSync,
+						psKick->ahDstSyncInfo,
+						abDstSyncEnable);
+				}
+#endif
+			for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+			{
+				if (abSrcSyncEnable[loop])
+				{
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+					SyncRollBackReadOp(psSyncInfo, SYNC_OP_CLASS_TQ_3D);
+#if defined(PDUMP)
+					if (PDumpIsCaptureFrameKM()
+							|| ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+					{
+						psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+					}
+#endif
+				}
+			}
+			for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+			{
+				if (abDstSyncEnable[loop])
+				{
+					psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+					SyncRollBackWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_3D);
+#if defined(PDUMP)
+					if (PDumpIsCaptureFrameKM()
+							|| ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+					{
+						psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+					}
+#endif
+				}
+			}
+		}
+
+		/* Command needed to be synchronised with the TA? */
+		if (psKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+			SyncRollBackWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_3D);
+		}
+
+		/* Command needed to be synchronised with the 3D? */
+		if (psKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+			SyncRollBackWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_3D);
+		}
+	}
+	else if (PVRSRV_OK != eError)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed."));
+		PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+				TRANSFER_TOKEN_SUBMIT);
+#if defined(SUPPORT_DMABUF) && defined(NO_HARDWARE)
+		PVRLinuxFenceCheckAll();
+#endif
+		return eError;
+	}
+#if defined(SUPPORT_DMABUF)
+	else if (ui32NumResvObjs && !bBlockingFences)
+	{
+		eError = PVRLinuxFenceProcess(&ui32FenceTag,
+				ui32NumResvObjs,
+				bBlockingFences,
+				psKick->ui32NumSrcSync,
+				psKick->ahSrcSyncInfo,
+				abSrcSyncEnable,
+				psKick->ui32NumDstSync,
+				psKick->ahDstSyncInfo,
+				abDstSyncEnable);
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+#endif
+
+#if defined(NO_HARDWARE)
+	if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
+	{
+		/* Update sync objects pretending that we have done the job*/
+		for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
+		{
+			if (abSrcSyncEnable[loop])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+				psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+			}
+		}
+
+		for (loop = 0; loop < psKick->ui32NumDstSync; loop++)
+		{
+			if (abDstSyncEnable[loop])
+			{
+				psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+				psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+			}
+		}
+
+		if (psKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+			psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		}
+
+		if (psKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+			psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		}
+	}
+#endif
+	PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
+			TRANSFER_TOKEN_SUBMIT);
+	return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick)
+					    
+{
+	PVRSRV_KERNEL_MEM_INFO  *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+	SGXMKIF_COMMAND sCommand = {0};
+	SGXMKIF_2DCMD_SHARED *ps2DCmd;
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+	PVRSRV_ERROR eError;
+	IMG_UINT32 i;
+	IMG_HANDLE hDevMemContext = IMG_NULL;
+#if defined(FIX_HW_BRN_31620)
+	hDevMemContext = psKick->hDevMemContext;
+#endif
+
+	if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	/* override QAC warning about stricter alignment */
+	/* PRQA S 3305 1 */
+	ps2DCmd =  CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+	/* Command needs to be synchronised with the TA? */
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+		ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);
+		ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr 	= psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr 	= psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+	else
+	{
+		ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr.uiAddr = 0;
+		ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr.uiAddr = 0;
+	}
+
+	/* Command needs to be synchronised with the 3D? */
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+		ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);	
+		ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+	else
+	{
+		ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr.uiAddr = 0;
+		ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr.uiAddr = 0;
+	}
+
+	/*
+	 * We allow the first source and destination sync objects to be the
+	 * same, which is why the read/write pending updates are delayed
+	 * until the transfer command has been updated with the current
+	 * values from the objects.
+	 */
+	ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+		ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+	}
+
+	if (psKick->hDstSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = psKick->hDstSyncInfo;
+
+		ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+		ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+		ps2DCmd->sDstSyncData.ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+		ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+		ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+		ps2DCmd->sDstSyncData.sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+
+		/* We can do this immediately as we only have one */
+		SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);
+	}
+	else
+	{
+		ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr.uiAddr = 0;
+		ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr.uiAddr = 0;
+		ps2DCmd->sDstSyncData.sReadOps2CompleteDevVAddr.uiAddr = 0;
+	}
+
+	/* Read/Write ops pending updates, delayed from above */
+	for (i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psSyncInfo = psKick->ahSrcSyncInfo[i];
+		SyncTakeReadOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);
+	}
+
+#if defined(PDUMP)
+	if (PDumpWillCapture(psKick->ui32PDumpFlags))
+	{
+		/* Pdump the command from the per context CCB */
+		PDUMPCOMMENT("Shared part of 2D command\r\n");
+		PDUMPMEM(ps2DCmd,
+				psCCBMemInfo,
+				psKick->ui32CCBDumpWOff,
+				sizeof(SGXMKIF_2DCMD_SHARED),
+				psKick->ui32PDumpFlags,
+				MAKEUNIQUETAG(psCCBMemInfo));
+
+		for (i = 0; i < psKick->ui32NumSrcSync; i++)
+		{
+			psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+			PDUMPCOMMENT("Tweak src surface write op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Tweak src surface read op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+		}
+
+		if (psKick->hDstSyncInfo != IMG_NULL)
+		{
+			IMG_UINT32 ui32PDumpReadOp2 = 0;
+			psSyncInfo = psKick->hDstSyncInfo;
+
+			PDUMPCOMMENT("Tweak dest surface write op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+
+			PDUMPCOMMENT("Tweak dest surface read op in 2D cmd\r\n");
+			PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
+					sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+			PDUMPCOMMENT("Tweak dest surface read op2 in 2D cmd\r\n");
+			PDUMPMEM(&ui32PDumpReadOp2,
+					psCCBMemInfo,
+					psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOps2PendingVal),
+					sizeof(ui32PDumpReadOp2),
+					psKick->ui32PDumpFlags,
+					MAKEUNIQUETAG(psCCBMemInfo));
+		}
+
+		/* Read/Write ops pending updates, delayed from above */
+		for (i = 0; i < psKick->ui32NumSrcSync; i++)
+		{
+			psSyncInfo = psKick->ahSrcSyncInfo[i];
+			psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT,
+									"TQ2D Src: PDump sync update: uiAddr = 0x%08x, ui32LastReadOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastReadOpDumpVal);
+#endif
+		}
+
+		if (psKick->hDstSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = psKick->hDstSyncInfo;
+			psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+#if defined(SUPPORT_PDUMP_SYNC_DEBUG)
+			PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_PERSISTENT,
+									"TQ2D Dst: PDump sync update: uiAddr = 0x%08x, ui32LastOpDumpVal = 0x%08x\r\n",
+									psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+									psSyncInfo->psSyncData->ui32LastOpDumpVal);
+#endif
+		}
+	}		
+#endif
+
+	sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr;
+	
+	eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags, hDevMemContext, IMG_FALSE);	
+
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		/* Client will retry, so undo the write ops pending increment
+		   done above.
+		 */
+#if defined(PDUMP)
+		if (PDumpIsCaptureFrameKM())
+		{
+			for (i = 0; i < psKick->ui32NumSrcSync; i++)
+			{
+				psSyncInfo = psKick->ahSrcSyncInfo[i];
+				psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+			}
+
+			if (psKick->hDstSyncInfo != IMG_NULL)
+			{
+				psSyncInfo = psKick->hDstSyncInfo;
+				psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+			}
+		}
+#endif
+
+		for (i = 0; i < psKick->ui32NumSrcSync; i++)
+		{
+			psSyncInfo = psKick->ahSrcSyncInfo[i];
+			SyncRollBackReadOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);
+		}
+
+		if (psKick->hDstSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = psKick->hDstSyncInfo;
+			SyncRollBackWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);
+		}
+
+		/* Command needed to be synchronised with the TA? */
+		if (psKick->hTASyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+			SyncRollBackWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);
+		}
+
+		/* Command needed to be synchronised with the 3D? */
+		if (psKick->h3DSyncInfo != IMG_NULL)
+		{
+			psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+			SyncRollBackWriteOp(psSyncInfo, SYNC_OP_CLASS_TQ_2D);
+		}
+	}
+
+	
+
+
+#if defined(NO_HARDWARE)
+	/* Update sync objects pretending that we have done the job*/
+	for(i = 0; i < psKick->ui32NumSrcSync; i++)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+		psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+	}
+
+	if (psKick->hDstSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo;
+
+		psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	if (psKick->hTASyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+		psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+
+	if (psKick->h3DSyncInfo != IMG_NULL)
+	{
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+		psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	}
+#if defined(SUPPORT_DMABUF)
+	PVRLinuxFenceCheckAll();
+#endif
+#endif
+
+	return eError;
+}
+#endif	/* SGX_FEATURE_2D_HARDWARE */
+#endif	/* TRANSFER_QUEUE */
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxutils.c b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxutils.c
new file mode 100644
index 0000000..4e0d683
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxutils.c
@@ -0,0 +1,1976 @@
+/*************************************************************************/ /*!
+@Title          Device specific utility routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+#include "sgxmmu.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>	// sprintf
+#include <linux/string.h>	// strncpy, strlen
+#else
+#include <stdio.h>
+#endif
+
+IMG_UINT64 ui64KickCount;
+
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE	* psDeviceNode, IMG_UINT32 ui32CallerID);
+#endif
+
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXPostActivePowerEvent
+
+ @Description
+
+	 post power event functionality (e.g. restart)
+
+ @Input	psDeviceNode : SGX Device Node
+ @Input	ui32CallerID - KERNEL_ID or ISR_ID
+
+ @Return   IMG_VOID :
+
+******************************************************************************/
+static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE	* psDeviceNode,
+										IMG_UINT32           ui32CallerID)
+{
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+	/* Update the counter for stats. */
+	psSGXHostCtl->ui32NumActivePowerEvents++;
+
+	if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SGXPostActivePowerEvent: SGX requests immediate restart"));
+		
+		/*
+			Events were queued during the active power
+			request, so SGX will need to be restarted.
+	     */
+		if (ui32CallerID == ISR_ID)
+		{
+			psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+		}
+		else
+		{
+			SGXScheduleProcessQueuesKM(psDeviceNode);
+		}
+	}
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXTestActivePowerEvent
+
+ @Description
+
+ Checks whether the microkernel has generated an active power event. If so,
+ 	perform the power transition.
+
+ @Input	psDeviceNode : SGX Device Node
+ @Input	ui32CallerID - KERNEL_ID or ISR_ID
+
+ @Return   IMG_VOID :
+
+******************************************************************************/
+IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE	*psDeviceNode,
+								  IMG_UINT32			ui32CallerID)
+{
+	PVRSRV_ERROR		eError = PVRSRV_OK;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+	/*
+	 * Quickly check (without lock) if there is an IDLE or APM event we should handle.
+	 * This check fails most of the time so we don't want to incur lock overhead.
+	 * Check the flags in the reverse order that microkernel clears them to prevent
+	 * us from seeing an inconsistent state.
+	 */
+	if ((((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0) &&
+		((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0)) ||
+		(((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0) &&
+		((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0)))
+	{
+		eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+		if (eError == PVRSRV_ERROR_RETRY)
+		{
+			return;
+		}
+		else if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXTestActivePowerEvent failed to acquire lock - "
+                    "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+			return;
+		}
+
+		/*
+		 * Check again (with lock) if IDLE event has been cleared or handled. A race
+		 * condition may allow multiple threads to pass the quick check.
+		 */
+		if(((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) == 0) &&
+			((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_IDLE) != 0))
+		{
+			psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_IDLE;
+			if (psDevInfo->bSGXIdle == IMG_FALSE)
+			{
+				psDevInfo->bSGXIdle = IMG_TRUE;
+				SysSGXIdleEntered();
+			}
+		}
+
+		/*
+		 * Check again (with lock) if APM event has been cleared or handled. A race
+		 * condition may allow multiple threads to pass the quick check.
+		 */
+		if (((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0) &&
+			((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0))
+		{
+			/* Microkernel is idle and is requesting to be powered down. */
+			psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
+#if !defined(SUPPORT_PDUMP_MULTI_PROCESS)
+		/* Suspend pdumping. */
+			PDUMPSUSPEND();
+#endif
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+			/*
+				Some power down code cannot be executed inside an MISR on
+				some platforms that use mutexes inside the power code.
+			 */
+			eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
+#else
+			eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+								PVRSRV_DEV_POWER_STATE_OFF);
+#endif
+			if (eError == PVRSRV_OK)
+			{
+				SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
+			}
+#if !defined(SUPPORT_PDUMP_MULTI_PROCESS)
+			/* Resume pdumping */
+			PDUMPRESUME();
+#endif
+		}
+
+		PVRSRVPowerUnlock(ui32CallerID);
+	}
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError));
+	}
+}
+
+
+/******************************************************************************
+ FUNCTION	: SGXAcquireKernelCCBSlot
+
+ PURPOSE	: Attempts to obtain a slot in the Kernel CCB
+
+ PARAMETERS	: psCCB - the CCB
+
+ RETURNS	: Address of space if available, IMG_NULL otherwise
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGXAcquireKernelCCBSlot)
+#endif
+static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psCCB)
+{
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		if(((*psCCB->pui32WriteOffset + 1) & 255) != *psCCB->pui32ReadOffset)
+		{
+			return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+		}
+
+		OSSleepms(1);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	/* Time out on waiting for CCB space */
+	return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+
+ @Function	SGXScheduleCCBCommand
+
+ @Description - Submits a CCB command and kicks the ukernel (without
+ 				power management)
+
+ @Input psDevInfo - pointer to device info
+ @Input eCmdType - see SGXMKIF_CMD_*
+ @Input psCommandData - kernel CCB command
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+ @Input ui32PDumpFlags
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE	*psDeviceNode,
+								   SGXMKIF_CMD_TYPE		eCmdType,
+								   SGXMKIF_COMMAND		*psCommandData,
+								   IMG_UINT32			ui32CallerID,
+								   IMG_UINT32			ui32PDumpFlags,
+								   IMG_HANDLE			hDevMemContext,
+								   IMG_BOOL				bLastInScene)
+{
+	PVRSRV_SGX_CCB_INFO *psKernelCCB;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+	SGXMKIF_COMMAND *psSGXCommand;
+	PVRSRV_SGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+#if defined(FIX_HW_BRN_31620)
+	IMG_UINT32 ui32CacheMasks[4];
+	IMG_UINT32 i;
+	MMU_CONTEXT		*psMMUContext;
+#endif
+#if defined(PDUMP)
+	IMG_VOID *pvDumpCommand;
+	IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	IMG_BOOL bPDumpActive = _PDumpIsProcessActive();
+#else
+	IMG_BOOL bPDumpActive = IMG_TRUE;
+#endif
+#else
+	PVR_UNREFERENCED_PARAMETER(ui32CallerID);
+	PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+	for(i=0;i<4;i++)
+	{
+		ui32CacheMasks[i] = 0;
+	}
+
+	psMMUContext = psDevInfo->hKernelMMUContext;
+	psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[0]);
+
+	/* Put the apps memory context in the bottom half */
+	if (hDevMemContext)
+	{
+		BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
+
+		psMMUContext = psBMContext->psMMUContext;
+		psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[2]);
+	}
+
+	/* If we have an outstanding flush request then set the cachecontrol bit */
+	if (ui32CacheMasks[0] || ui32CacheMasks[1] || ui32CacheMasks[2] || ui32CacheMasks[3])
+	{
+		psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+	}
+#endif
+
+#if defined(FIX_HW_BRN_28889)
+	/*
+		If the data cache and bif cache need invalidating there has been a cleanup
+		request. Therefore, we need to send the invalidate separately and wait
+		for it to complete.
+	*/
+	if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) &&
+		 ((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
+		 ((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
+	{
+	#if defined(PDUMP)
+		PVRSRV_KERNEL_MEM_INFO	*psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+	#endif
+		SGXMKIF_HOST_CTL	*psSGXHostCtl = psDevInfo->psSGXHostCtl;
+		SGXMKIF_COMMAND		sCacheCommand = {0};
+
+		eError = SGXScheduleCCBCommand(psDeviceNode,
+									   SGXMKIF_CMD_PROCESS_QUEUES,
+									   &sCacheCommand,
+									   ui32CallerID,
+									   ui32PDumpFlags,
+									   hDevMemContext,
+									   bLastInScene);
+		if (eError != PVRSRV_OK)
+		{
+			goto Exit;
+		}
+
+		/* Wait for the invalidate to happen */
+		#if !defined(NO_HARDWARE)
+		if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
+						  PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+						  PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+						  2 * MAX_HW_TIME_US,
+						  MAX_HW_TIME_US/WAIT_TRY_COUNT,
+						  IMG_FALSE) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommand: Wait for uKernel to Invalidate BIF cache failed"));
+			PVR_DBG_BREAK;
+		}
+		#endif
+
+		#if defined(PDUMP)
+		/* Pdump the poll as well. */
+		PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
+		PDUMPMEMPOL(psSGXHostCtlMemInfo,
+					offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
+					PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+					PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					0,
+					MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+		#endif /* PDUMP */
+
+		psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
+		PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+	}
+#else
+	PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+	if ((eCmdType != SGXMKIF_CMD_FLUSHPDCACHE) && (psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_BIF_PD))
+	{
+		SGXMKIF_COMMAND		sPDECacheCommand = {0};
+		IMG_DEV_PHYADDR		sDevPAddr;
+
+		/* Put the kernel info in the top 1/2 of the data */
+		psMMUContext = psDevInfo->hKernelMMUContext;
+
+		psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
+		sPDECacheCommand.ui32Data[0] = sDevPAddr.uiAddr | 1;
+		sPDECacheCommand.ui32Data[1] = ui32CacheMasks[0];
+		sPDECacheCommand.ui32Data[2] = ui32CacheMasks[1];
+
+		/* Put the apps memory context in the bottom half */
+		if (hDevMemContext)
+		{
+			BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
+
+			psMMUContext = psBMContext->psMMUContext;
+
+			psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
+			/* Or in 1 to the lsb to show we have a valid context */
+			sPDECacheCommand.ui32Data[3] = sDevPAddr.uiAddr | 1;
+			sPDECacheCommand.ui32Data[4] = ui32CacheMasks[2];
+			sPDECacheCommand.ui32Data[5] = ui32CacheMasks[3];
+		}
+
+		/* Only do a kick if there is any update */
+		if (sPDECacheCommand.ui32Data[1] | sPDECacheCommand.ui32Data[2] | sPDECacheCommand.ui32Data[4] |
+			sPDECacheCommand.ui32Data[5])
+		{
+			eError = SGXScheduleCCBCommand(psDeviceNode,
+										   SGXMKIF_CMD_FLUSHPDCACHE,
+										   &sPDECacheCommand,
+										   ui32CallerID,
+										   ui32PDumpFlags,
+										   hDevMemContext,
+										   bLastInScene);
+			if (eError != PVRSRV_OK)
+			{
+				goto Exit;
+			}
+		}
+	}
+#endif
+	psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+	psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+	/* Wait for CCB space timed out */
+	if(!psSGXCommand)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Wait for CCB space timed out")) ;
+		eError = PVRSRV_ERROR_TIMEOUT;
+		goto Exit;
+	}
+
+	/* embed cache control word */
+	psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+	/* Accumulate any cache invalidates that may have happened */
+	psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+	/* and clear it */
+	psDevInfo->ui32CacheControl = 0;
+
+	/* Copy command data over */
+	*psSGXCommand = *psCommandData;
+
+	if (eCmdType >= SGXMKIF_CMD_MAX)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Unknown command type: %d", eCmdType)) ;
+		eError = PVRSRV_ERROR_INVALID_CCB_COMMAND;
+		goto Exit;
+	}
+
+	if (eCmdType == SGXMKIF_CMD_2D ||
+		eCmdType == SGXMKIF_CMD_TRANSFER ||
+		((eCmdType == SGXMKIF_CMD_TA) && bLastInScene))
+	{
+		SYS_DATA *psSysData;
+
+		/* CPU cache clean control */
+		SysAcquireData(&psSysData);
+
+		if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+		{
+			OSFlushCPUCacheKM();
+		}
+		else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+		{
+			OSCleanCPUCacheKM();
+		}
+
+		/* Clear the pending op */
+		psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+	}
+
+	PVR_ASSERT(eCmdType < SGXMKIF_CMD_MAX);
+	psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];	/* PRQA S 3689 */ /* misuse of enums for bounds checking */
+
+#if defined(PDUMP)
+	if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+		(bPDumpActive == IMG_TRUE) )
+	{
+		/* Poll for space in the CCB. */
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
+		PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+					offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+					(psKernelCCB->ui32CCBDumpWOff + 1) & 0xff,
+					0xff,
+					PDUMP_POLL_OPERATOR_NOTEQUAL,
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB command (type == %d)\r\n", eCmdType);
+		pvDumpCommand = (IMG_VOID *)((IMG_UINT8 *)psKernelCCB->psCCBMemInfo->pvLinAddrKM + (*psKernelCCB->pui32WriteOffset * sizeof(SGXMKIF_COMMAND)));
+
+		PDUMPMEM(pvDumpCommand,
+					psKernelCCB->psCCBMemInfo,
+					psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND),
+					sizeof(SGXMKIF_COMMAND),
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+		/* Overwrite cache control with pdump shadow */
+		PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+					psKernelCCB->psCCBMemInfo,
+					psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
+					offsetof(SGXMKIF_COMMAND, ui32CacheControl),
+					sizeof(IMG_UINT32),
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+		if (PDumpIsCaptureFrameKM()
+		|| ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+		{
+			/* Clear cache invalidate shadow */
+			psDevInfo->sPDContext.ui32CacheControl = 0;
+		}
+	}
+#endif
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+	/* Make sure the previous command has been read before send the next one */
+	eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
+								*psKernelCCB->pui32WriteOffset,
+								0xFF,
+								MAX_HW_TIME_US,
+								MAX_HW_TIME_US/WAIT_TRY_COUNT,
+								IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Timeout waiting for previous command to be read")) ;
+		eError = PVRSRV_ERROR_TIMEOUT;
+		goto Exit;
+	}
+#endif
+
+	/*
+		Increment the write offset
+	*/
+	*psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+	if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+		(bPDumpActive == IMG_TRUE) )
+	{
+	#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for previous Kernel CCB CMD to be read\r\n");
+		PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+					offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+					(psKernelCCB->ui32CCBDumpWOff),
+					0xFF,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					ui32PDumpFlags,
+					MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+	#endif
+
+		if (PDumpIsCaptureFrameKM()
+		|| ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+		{
+			psKernelCCB->ui32CCBDumpWOff = (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+			psDevInfo->ui32KernelCCBEventKickerDumpVal = (psDevInfo->ui32KernelCCBEventKickerDumpVal + 1) & 0xFF;
+		}
+
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB write offset\r\n");
+		PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+				 psKernelCCB->psCCBCtlMemInfo,
+				 offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+				 sizeof(IMG_UINT32),
+				 ui32PDumpFlags,
+				 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB event kicker\r\n");
+		PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+				 psDevInfo->psKernelCCBEventKickerMemInfo,
+				 0,
+				 sizeof(IMG_UINT32),
+				 ui32PDumpFlags,
+				 MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+		PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kick the SGX microkernel\r\n");
+	#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK, ui32PDumpFlags);
+	#else
+		PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK, ui32PDumpFlags);
+	#endif
+	}
+#endif
+
+	*psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+
+	/*
+	 * New command submission is considered a proper handling of any pending
+	 * IDLE or APM event, so mark them as handled to prevent other host threads
+	 * from taking action.
+	 */
+	psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_IDLE;
+	psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
+	OSWriteMemoryBarrier();
+
+	/* Order is importent for post processor! */
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
+			MKSYNC_TOKEN_KERNEL_CCB_OFFSET, *psKernelCCB->pui32WriteOffset);
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
+			MKSYNC_TOKEN_CORE_CLK, psDevInfo->ui32CoreClockSpeed);
+	PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
+			MKSYNC_TOKEN_UKERNEL_CLK, psDevInfo->ui32uKernelTimerClock);
+
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+				EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+	OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+				SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+				EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+	OSMemoryBarrier();
+
+#if defined(NO_HARDWARE)
+	/* Increment read offset */
+	*psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+	ui64KickCount++;
+Exit:
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXScheduleCCBCommandKM
+
+ @Description - Submits a CCB command and kicks the ukernel
+
+ @Input psDeviceNode - pointer to SGX device node
+ @Input eCmdType - see SGXMKIF_CMD_*
+ @Input psCommandData - kernel CCB command
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+ @Input ui32PDumpFlags
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE		*psDeviceNode,
+									 SGXMKIF_CMD_TYPE		eCmdType,
+									 SGXMKIF_COMMAND		*psCommandData,
+									 IMG_UINT32				ui32CallerID,
+									 IMG_UINT32				ui32PDumpFlags,
+									 IMG_HANDLE				hDevMemContext,
+									 IMG_BOOL				bLastInScene)
+{
+	PVRSRV_ERROR	eError;
+	PVRSRV_SGXDEV_INFO	*psDevInfo = psDeviceNode->pvDevice;
+
+	eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		if (ui32CallerID == ISR_ID)
+		{
+			SYS_DATA *psSysData;
+			
+			/*
+				ISR failed to acquire lock so it must be held by a kernel thread.
+				Bring up and kick SGX if necessary when the lock is available.
+			*/
+			psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+			eError = PVRSRV_OK;
+
+			SysAcquireData(&psSysData);
+			OSScheduleMISR(psSysData);
+		}
+		else
+		{
+			/*
+				Return to srvclient for retry.
+			*/
+		}
+
+		return eError;
+	}
+	else if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+				"ui32CallerID:%d eError:%u", ui32CallerID, eError));
+		return eError;
+	}
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	PDUMP_LOCK();
+#endif
+	/* Note that a power-up has been dumped in the init phase. */
+	PDUMPSUSPEND();
+
+	/* Ensure that SGX is powered up before kicking the ukernel. */
+	eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE_ON);
+
+	PDUMPRESUME();
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	PDUMP_UNLOCK();
+#endif
+
+	if (eError == PVRSRV_OK)
+	{
+		psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to power up device - "
+				 "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+		PVRSRVPowerUnlock(ui32CallerID);
+		return eError;
+	}
+
+	SysSGXCommandPending(psDevInfo->bSGXIdle);
+	psDevInfo->bSGXIdle = IMG_FALSE;
+
+	eError = SGXScheduleCCBCommand(psDeviceNode, eCmdType, psCommandData, ui32CallerID, ui32PDumpFlags, hDevMemContext, bLastInScene);
+
+	PVRSRVPowerUnlock(ui32CallerID);
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXScheduleProcessQueuesKM
+
+ @Description - Software command complete handler
+
+ @Input psDeviceNode - SGX device node
+
+******************************************************************************/
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVRSRV_ERROR 		eError;
+	PVRSRV_SGXDEV_INFO 	*psDevInfo = psDeviceNode->pvDevice;
+	SGXMKIF_HOST_CTL	*psHostCtl;
+	IMG_UINT32			ui32PowerStatus;
+	SGXMKIF_COMMAND		sCommand = {0};
+
+	if (psDevInfo->psKernelSGXHostCtlMemInfo == IMG_NULL)
+	{
+		/* Part2 hasn't run yet, we can't do anything */
+		return PVRSRV_OK;
+	}
+
+	psHostCtl = psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+	ui32PowerStatus = psHostCtl->ui32PowerStatus;
+	if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+	{
+		/* The ukernel has no work to be done, so don't waste power. */
+		return PVRSRV_OK;
+	}
+
+	eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_PROCESS_QUEUES, &sCommand, ISR_ID, 0, IMG_NULL, IMG_FALSE);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SGXScheduleProcessQueuesKM failed to schedule CCB command: %u", eError));
+		return eError;
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SGXIsDevicePowered
+
+ @Description
+
+	Whether the device is powered, for the purposes of lockup detection.
+
+ @Input psDeviceNode - pointer to device node
+
+ @Return   IMG_BOOL  : Whether device is powered
+
+******************************************************************************/
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+/*!
+*******************************************************************************
+
+ @Function	SGXGetInternalDevInfoKM
+
+ @Description
+	Gets device information that is not intended to be passed
+	on beyond the srvclient libs.
+
+ @Input hDevCookie
+
+ @Output psSGXInternalDevInfo
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+									SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo)
+{
+	PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+	psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
+
+	/* This should be patched up by OS bridge code */
+	psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
+		(IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
+
+	return PVRSRV_OK;
+}
+
+
+/*****************************************************************************
+ FUNCTION	: SGXCleanupRequest
+
+ PURPOSE	: Wait for the microkernel to clean up its references to either a
+ 				render context or render target.
+
+ PARAMETERS	:	psDeviceNode - SGX device node
+ 				psHWDataDevVAddr - Device Address of the resource
+				ui32CleanupType - PVRSRV_CLEANUPCMD_*
+				bForceCleanup - Skips sync polling
+
+ RETURNS	: error status
+*****************************************************************************/
+PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+							   IMG_DEV_VIRTADDR   *psHWDataDevVAddr,
+							   IMG_UINT32          ui32CleanupType,
+							   IMG_BOOL            bForceCleanup)
+{
+	PVRSRV_ERROR			eError;
+	PVRSRV_SGXDEV_INFO		*psDevInfo = psDeviceNode->pvDevice;
+	PVRSRV_KERNEL_MEM_INFO	*psHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+	SGXMKIF_HOST_CTL		*psHostCtl = psHostCtlMemInfo->pvLinAddrKM;
+
+	SGXMKIF_COMMAND		sCommand = {0};
+
+
+	if (bForceCleanup != FORCE_CLEANUP)
+	{
+		sCommand.ui32Data[0] = ui32CleanupType;
+		sCommand.ui32Data[1] = (psHWDataDevVAddr == IMG_NULL) ? 0 : psHWDataDevVAddr->uiAddr;
+		PDUMPCOMMENTWITHFLAGS(0, "Request ukernel resource clean-up, Type %u, Data 0x%X", sCommand.ui32Data[0], sCommand.ui32Data[1]);
+	
+		eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CLEANUP, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
+		if (eError != PVRSRV_OK)
+		{
+				PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+				SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+				PVR_DBG_BREAK;
+				return eError;
+		}
+		
+		/* Wait for the uKernel process the cleanup request */
+		#if !defined(NO_HARDWARE)
+		if(PollForValueKM(&psHostCtl->ui32CleanupStatus,
+						  PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+						  PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+						  10 * MAX_HW_TIME_US,
+						  1000,
+						  IMG_TRUE) != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType));
+			eError = PVRSRV_ERROR_TIMEOUT;
+			SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+			PVR_DBG_BREAK;
+		}
+		#endif
+	
+		#if defined(PDUMP)
+		/*
+			Pdump the poll as well.
+			Note:
+			We don't expect the cleanup to report busy as the client should have
+			ensured the resource has been finished with before requesting it's
+			cleanup. This isn't true of the abnormal termination case but we
+			don't expect to PDump that. Unless/until PDump has flow control
+			there isn't anything else we can do.
+		*/
+		PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
+		PDUMPMEMPOL(psHostCtlMemInfo,
+					offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
+					PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
+					PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
+					PDUMP_POLL_OPERATOR_EQUAL,
+					0,
+					MAKEUNIQUETAG(psHostCtlMemInfo));
+		#endif /* PDUMP */
+	
+		if (eError != PVRSRV_OK)
+		{
+			return eError;
+		}
+	}
+
+	if (psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_BUSY)
+	{
+		/* Only one flag should be set */
+		PVR_ASSERT((psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_DONE) == 0);
+		eError = PVRSRV_ERROR_RETRY;
+		psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_BUSY);
+	}
+	else
+	{
+		eError = PVRSRV_OK;
+		psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE);
+	}
+	
+	PDUMPMEM(IMG_NULL, psHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psHostCtlMemInfo));
+
+	/* Request the cache invalidate */
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	psDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
+#else
+	psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
+#endif
+	return eError;
+}
+
+
+typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+    PVRSRV_KERNEL_MEM_INFO *psHWRenderContextMemInfo;
+    IMG_HANDLE hBlockAlloc;
+	PRESMAN_ITEM psResItem;
+	IMG_BOOL bCleanupTimerRunning;
+	IMG_PVOID pvTimeData;
+} SGX_HW_RENDER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID		pvParam,
+													  IMG_UINT32	ui32Param,
+													  IMG_BOOL		bForceCleanup)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	eError = SGXCleanupRequest(psCleanup->psDeviceNode,
+					  &psCleanup->psHWRenderContextMemInfo->sDevVAddr,
+					  PVRSRV_CLEANUPCMD_RC,
+					  bForceCleanup);
+
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		if (!psCleanup->bCleanupTimerRunning)
+		{
+			OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+			psCleanup->bCleanupTimerRunning = IMG_TRUE;
+		}
+		else
+		{
+			if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+			{
+				eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+				psCleanup->bCleanupTimerRunning = IMG_FALSE;
+				OSTimeDestroy(psCleanup->pvTimeData);
+			}
+		}
+	}
+	else
+	{
+		if (psCleanup->bCleanupTimerRunning)
+		{
+			OSTimeDestroy(psCleanup->pvTimeData);
+		}
+	}
+
+	if (eError != PVRSRV_ERROR_RETRY)
+	{
+	    /* Free the Device Mem allocated */
+	    PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+	            psCleanup->psHWRenderContextMemInfo);
+	
+	    /* Finally, free the cleanup structure itself */
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+				  psCleanup,
+				  psCleanup->hBlockAlloc);
+		/*not nulling pointer, copy on stack*/
+	}
+
+	return eError;
+}
+
+typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+    PVRSRV_KERNEL_MEM_INFO *psHWTransferContextMemInfo;
+	IMG_HANDLE hBlockAlloc;
+	PRESMAN_ITEM psResItem;
+	IMG_BOOL bCleanupTimerRunning;
+	IMG_PVOID pvTimeData;
+} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID	pvParam,
+														IMG_UINT32	ui32Param,
+														IMG_BOOL	bForceCleanup)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+	eError = SGXCleanupRequest(psCleanup->psDeviceNode,
+					  &psCleanup->psHWTransferContextMemInfo->sDevVAddr,
+					  PVRSRV_CLEANUPCMD_TC,
+					  bForceCleanup);
+
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		if (!psCleanup->bCleanupTimerRunning)
+		{
+			OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+			psCleanup->bCleanupTimerRunning = IMG_TRUE;
+		}
+		else
+		{
+			if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+			{
+				eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+				psCleanup->bCleanupTimerRunning = IMG_FALSE;
+				OSTimeDestroy(psCleanup->pvTimeData);
+			}
+		}
+	}
+	else
+	{
+		if (psCleanup->bCleanupTimerRunning)
+		{
+			OSTimeDestroy(psCleanup->pvTimeData);
+		}
+	}
+
+	if (eError != PVRSRV_ERROR_RETRY)
+	{
+	    /* Free the Device Mem allocated */
+	    PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+	            psCleanup->psHWTransferContextMemInfo);
+	
+	    /* Finally, free the cleanup structure itself */
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+				  psCleanup,
+				  psCleanup->hBlockAlloc);
+		/*not nulling pointer, copy on stack*/
+	}
+
+	return eError;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE				hDeviceNode,
+                                        IMG_CPU_VIRTADDR        *psHWRenderContextCpuVAddr,
+                                        IMG_UINT32              ui32HWRenderContextSize,
+                                        IMG_UINT32              ui32OffsetToPDDevPAddr,
+                                        IMG_HANDLE              hDevMemContext,
+                                        IMG_DEV_VIRTADDR        *psHWRenderContextDevVAddr,
+										PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+    PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hDeviceNode;
+	DEVICE_MEMORY_INFO	*psDevMemoryInfo;
+    DEVICE_MEMORY_HEAP_INFO *psHeapInfo;
+    IMG_HANDLE hDevMemContextInt;
+    MMU_CONTEXT *psMMUContext;
+    IMG_DEV_PHYADDR sPDDevPAddr;
+    int iPtrByte;
+    IMG_UINT8 *pSrc;
+    IMG_UINT8 *pDst;
+	PRESMAN_ITEM psResItem;
+	IMG_UINT32 ui32PDDevPAddrInDirListFormat;
+	IMG_UINT8 *pStartPDDevPAddr, *pEndPDDevPAddr;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+						(IMG_VOID **)&psCleanup,
+						&hBlockAlloc,
+						"SGX Hardware Render Context Cleanup");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate memory for SGX_HW_RENDER_CONTEXT_CLEANUP structure"));
+		goto exit0;
+	}
+
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+    psHeapInfo = &psDevMemoryInfo->psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID];
+
+    eError = PVRSRVAllocDeviceMemKM(hDeviceNode,
+                               psPerProc,
+                               psHeapInfo->hDevMemHeap,
+                               PVRSRV_MEM_READ | PVRSRV_MEM_WRITE 
+                                 | PVRSRV_MEM_NO_SYNCOBJ | PVRSRV_MEM_EDM_PROTECT 
+                                 | PVRSRV_MEM_CACHE_CONSISTENT,
+                               ui32HWRenderContextSize,
+                               32,
+                               IMG_NULL,
+                               0,
+                               0,0,0,IMG_NULL,	/* No sparse mapping data */
+                               &psCleanup->psHWRenderContextMemInfo,
+                               "HW Render Context");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate device memory for HW Render Context"));
+		goto exit1;
+	}
+	/* Ensure that the offset of Page directory dev physical address field is within the allocated context memory */
+	pStartPDDevPAddr = (IMG_UINT8 *)(psCleanup->psHWRenderContextMemInfo->pvLinAddrKM) + ui32OffsetToPDDevPAddr;
+	pEndPDDevPAddr = pStartPDDevPAddr + sizeof(ui32PDDevPAddrInDirListFormat) - 1;
+
+	if (pStartPDDevPAddr < (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM || 
+			pEndPDDevPAddr >= (IMG_UINT8 *)(psCleanup->psHWRenderContextMemInfo->pvLinAddrKM) + ui32HWRenderContextSize)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Offset of page directory device physical address is invalid"));
+		goto exit2;
+	}
+
+    eError = OSCopyFromUser(psPerProc,
+                            psCleanup->psHWRenderContextMemInfo->pvLinAddrKM,
+                            psHWRenderContextCpuVAddr,
+                            ui32HWRenderContextSize);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't copy user-mode copy of HWContext into device memory"));
+		goto exit2;
+	}
+
+    /* Pass the DevVAddr of the new context back up through the bridge */
+    psHWRenderContextDevVAddr->uiAddr = psCleanup->psHWRenderContextMemInfo->sDevVAddr.uiAddr;
+
+    /* Retrieve the PDDevPAddr */
+    eError = PVRSRVLookupHandle(psPerProc->psHandleBase, 
+                           &hDevMemContextInt,
+                           hDevMemContext,
+                           PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+    if (eError != PVRSRV_OK)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Can't lookup DevMem Context"));
+        goto exit2;
+    }
+
+    psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
+    sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
+
+	/* 
+	   The PDDevPAddr needs to be shifted-down, as the uKernel expects it in the
+	   format it will be inserted into the DirList registers in.
+	*/
+	ui32PDDevPAddrInDirListFormat = (IMG_UINT32)(sPDDevPAddr.uiAddr >> SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+    /* 
+       patch-in the Page-Directory Device-Physical address. Note that this is
+       copied-in one byte at a time, as we have no guarantee that the usermode-
+       provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+       current CPU architecture.
+     */
+	pSrc = (IMG_UINT8 *)&ui32PDDevPAddrInDirListFormat;
+    pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
+    pDst += ui32OffsetToPDDevPAddr;
+
+    for (iPtrByte = 0; iPtrByte < sizeof(ui32PDDevPAddrInDirListFormat); iPtrByte++)
+    {
+        pDst[iPtrByte] = pSrc[iPtrByte];
+    }
+
+#if defined(PDUMP)
+    /* PDUMP the HW context */
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Render context struct");
+
+	PDUMPMEM(
+        IMG_NULL, 
+        psCleanup->psHWRenderContextMemInfo,
+        0, 
+        ui32HWRenderContextSize, 
+        PDUMP_FLAGS_CONTINUOUS, 
+        MAKEUNIQUETAG(psCleanup->psHWRenderContextMemInfo));
+
+    /* PDUMP the PDDevPAddr */
+	PDUMPCOMMENT("Page directory address in HW render context");
+    PDUMPPDDEVPADDR(
+            psCleanup->psHWRenderContextMemInfo,
+            ui32OffsetToPDDevPAddr,
+            sPDDevPAddr,
+            MAKEUNIQUETAG(psCleanup->psHWRenderContextMemInfo),
+            PDUMP_PD_UNIQUETAG);
+#endif
+
+	psCleanup->hBlockAlloc = hBlockAlloc;
+	psCleanup->psDeviceNode = psDeviceNode;
+	psCleanup->bCleanupTimerRunning = IMG_FALSE;
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_HW_RENDER_CONTEXT,
+								  (IMG_VOID *)psCleanup,
+								  0,
+								  &SGXCleanupHWRenderContextCallback);
+
+    if (psResItem == IMG_NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: ResManRegisterRes failed"));
+        goto exit2;
+    }
+
+	psCleanup->psResItem = psResItem;
+
+	return (IMG_HANDLE)psCleanup;
+
+/* Error exit paths */
+exit2:
+	 PVRSRVFreeDeviceMemKM(hDeviceNode,
+                           psCleanup->psHWRenderContextMemInfo);
+exit1:
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+              sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+              psCleanup,
+              psCleanup->hBlockAlloc);
+    /*not nulling pointer, out of scope*/
+exit0:
+    return IMG_NULL;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext, IMG_BOOL bForceCleanup)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+
+	PVR_ASSERT(hHWRenderContext != IMG_NULL);
+
+	psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+
+	if (psCleanup == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWRenderContextKM: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = ResManFreeResByPtr(psCleanup->psResItem, bForceCleanup);
+
+	return eError;
+}
+
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE				hDeviceNode,
+                                          IMG_CPU_VIRTADDR          *psHWTransferContextCpuVAddr,
+                                          IMG_UINT32                ui32HWTransferContextSize,
+                                          IMG_UINT32                ui32OffsetToPDDevPAddr,
+                                          IMG_HANDLE                hDevMemContext,
+                                          IMG_DEV_VIRTADDR          *psHWTransferContextDevVAddr,
+										  PVRSRV_PER_PROCESS_DATA	*psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+    PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hDeviceNode;
+	DEVICE_MEMORY_INFO	*psDevMemoryInfo;
+    DEVICE_MEMORY_HEAP_INFO *psHeapInfo;
+    IMG_HANDLE hDevMemContextInt;
+    MMU_CONTEXT *psMMUContext;
+    IMG_DEV_PHYADDR sPDDevPAddr;
+    int iPtrByte;
+    IMG_UINT8 *pSrc;
+    IMG_UINT8 *pDst;
+	PRESMAN_ITEM psResItem;
+	IMG_UINT32 ui32PDDevPAddrInDirListFormat;
+	IMG_UINT8 *pStartPDDevPAddr, *pEndPDDevPAddr;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+						(IMG_VOID **)&psCleanup,
+						&hBlockAlloc,
+						"SGX Hardware Transfer Context Cleanup");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate memory for SGX_HW_TRANSFER_CONTEXT_CLEANUP structure"));
+		goto exit0;
+	}
+
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+    psHeapInfo = &psDevMemoryInfo->psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID];
+
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Allocate HW Transfer context");
+    eError = PVRSRVAllocDeviceMemKM(hDeviceNode,
+                               psPerProc,
+                               psHeapInfo->hDevMemHeap,
+                               PVRSRV_MEM_READ | PVRSRV_MEM_WRITE 
+                                 | PVRSRV_MEM_NO_SYNCOBJ | PVRSRV_MEM_EDM_PROTECT 
+                                 | PVRSRV_MEM_CACHE_CONSISTENT,
+                               ui32HWTransferContextSize,
+                               32,
+                               IMG_NULL,
+                               0,
+                               0,0,0,IMG_NULL,	/* No sparse mapping data */
+                               &psCleanup->psHWTransferContextMemInfo,
+                               "HW Render Context");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate device memory for HW Render Context"));
+		goto exit1;
+	}
+
+	/* Ensure that the offset of Page directory dev physical address field is within the allocated context memory */
+	pStartPDDevPAddr = (IMG_UINT8 *)(psCleanup->psHWTransferContextMemInfo->pvLinAddrKM) + ui32OffsetToPDDevPAddr;
+	pEndPDDevPAddr = pStartPDDevPAddr + sizeof(ui32PDDevPAddrInDirListFormat) - 1;
+
+	if (pStartPDDevPAddr < (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM || 
+			pEndPDDevPAddr >= (IMG_UINT8 *)(psCleanup->psHWTransferContextMemInfo->pvLinAddrKM) + ui32HWTransferContextSize)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Offset of page directory device physical address is invalid"));
+		goto exit2;
+	}
+
+    eError = OSCopyFromUser(psPerProc,
+                            psCleanup->psHWTransferContextMemInfo->pvLinAddrKM,
+                            psHWTransferContextCpuVAddr,
+                            ui32HWTransferContextSize);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't copy user-mode copy of HWContext into device memory"));
+		goto exit2;
+	}
+
+    /* Pass the DevVAddr of the new context back up through the bridge */
+    psHWTransferContextDevVAddr->uiAddr = psCleanup->psHWTransferContextMemInfo->sDevVAddr.uiAddr;
+
+    /* Retrieve the PDDevPAddr */
+    eError = PVRSRVLookupHandle(psPerProc->psHandleBase, 
+                           &hDevMemContextInt,
+                           hDevMemContext,
+                           PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+    if (eError != PVRSRV_OK)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Can't lookup DevMem Context"));
+        goto exit2;
+    }
+
+    psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
+    sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
+
+	/* 
+	   The PDDevPAddr needs to be shifted-down, as the uKernel expects it in the
+	   format it will be inserted into the DirList registers in.
+	*/
+	ui32PDDevPAddrInDirListFormat = (IMG_UINT32)(sPDDevPAddr.uiAddr >> SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+    /* 
+       patch-in the Page-Directory Device-Physical address. Note that this is
+       copied-in one byte at a time, as we have no guarantee that the usermode-
+       provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+       current CPU architecture.
+     */
+	pSrc = (IMG_UINT8 *)&ui32PDDevPAddrInDirListFormat;
+    pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
+    pDst += ui32OffsetToPDDevPAddr;
+
+    for (iPtrByte = 0; iPtrByte < sizeof(ui32PDDevPAddrInDirListFormat); iPtrByte++)
+    {
+        pDst[iPtrByte] = pSrc[iPtrByte];
+    }
+
+#if defined(PDUMP)
+    /* PDUMP the HW Transfer Context */
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Transfer context struct");
+
+	PDUMPMEM(
+        IMG_NULL, 
+        psCleanup->psHWTransferContextMemInfo,
+        0, 
+        ui32HWTransferContextSize, 
+        PDUMP_FLAGS_CONTINUOUS, 
+        MAKEUNIQUETAG(psCleanup->psHWTransferContextMemInfo));
+
+    /* PDUMP the PDDevPAddr */
+	PDUMPCOMMENT("Page directory address in HW transfer context");
+
+    PDUMPPDDEVPADDR(
+            psCleanup->psHWTransferContextMemInfo,
+            ui32OffsetToPDDevPAddr,
+            sPDDevPAddr,
+            MAKEUNIQUETAG(psCleanup->psHWTransferContextMemInfo),
+            PDUMP_PD_UNIQUETAG);
+#endif
+
+	psCleanup->hBlockAlloc = hBlockAlloc;
+	psCleanup->psDeviceNode = psDeviceNode;
+	psCleanup->bCleanupTimerRunning = IMG_FALSE;
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+								  psCleanup,
+								  0,
+								  &SGXCleanupHWTransferContextCallback);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: ResManRegisterRes failed"));
+        goto exit2;
+    }
+
+	psCleanup->psResItem = psResItem;
+
+	return (IMG_HANDLE)psCleanup;
+
+/* Error exit paths */
+exit2:
+    PVRSRVFreeDeviceMemKM(hDeviceNode,
+            psCleanup->psHWTransferContextMemInfo);
+exit1:
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+              sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+              psCleanup,
+              psCleanup->hBlockAlloc);
+    /*not nulling pointer, out of scope*/
+
+exit0:
+    return IMG_NULL;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext, IMG_BOOL bForceCleanup)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+
+	PVR_ASSERT(hHWTransferContext != IMG_NULL);
+
+	psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+	if (psCleanup == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: invalid parameter"));
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	eError = ResManFreeResByPtr(psCleanup->psResItem, bForceCleanup);
+
+	return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXSetTransferContextPriorityKM(
+                IMG_HANDLE hDeviceNode,
+                IMG_HANDLE hHWTransferContext,
+                IMG_UINT32 ui32Priority,
+                IMG_UINT32 ui32OffsetOfPriorityField)
+{
+	SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+    IMG_UINT8 *pSrc;
+    IMG_UINT8 *pDst;
+    int iPtrByte;
+	PVR_UNREFERENCED_PARAMETER(hDeviceNode);
+
+    if (hHWTransferContext != IMG_NULL)
+    {
+        psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+        if ((ui32OffsetOfPriorityField + sizeof(ui32Priority)) 
+            >= psCleanup->psHWTransferContextMemInfo->uAllocSize)
+        {
+            PVR_DPF((
+                PVR_DBG_ERROR, 
+                "SGXSetTransferContextPriorityKM: invalid context prioirty offset"));
+
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+        /*
+           cannot be sure that offset (passed from user-land) is safe to deref
+           as a word-ptr on current CPU arch: copy one byte at a time.
+         */
+        pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
+        pDst += ui32OffsetOfPriorityField;
+        pSrc = (IMG_UINT8 *)&ui32Priority;
+
+        for (iPtrByte = 0; iPtrByte < sizeof(ui32Priority); iPtrByte++)
+        {
+            pDst[iPtrByte] = pSrc[iPtrByte];
+        }
+    }
+    return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXSetRenderContextPriorityKM(
+                IMG_HANDLE hDeviceNode,
+                IMG_HANDLE hHWRenderContext,
+                IMG_UINT32 ui32Priority,
+                IMG_UINT32 ui32OffsetOfPriorityField)
+{
+	SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+    IMG_UINT8 *pSrc;
+    IMG_UINT8 *pDst;
+    int iPtrByte;
+	PVR_UNREFERENCED_PARAMETER(hDeviceNode);
+
+    if (hHWRenderContext != IMG_NULL)
+    {
+        psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+        if ((ui32OffsetOfPriorityField + sizeof(ui32Priority)) 
+            >= psCleanup->psHWRenderContextMemInfo->uAllocSize)
+        {
+            PVR_DPF((
+                PVR_DBG_ERROR, 
+                "SGXSetContextPriorityKM: invalid HWRenderContext prioirty offset"));
+
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+        /*
+           cannot be sure that offset (passed from user-land) is safe to deref
+           as a word-ptr on current CPU arch: copy one byte at a time.
+         */
+        pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
+        pDst += ui32OffsetOfPriorityField;
+
+        pSrc = (IMG_UINT8 *)&ui32Priority;
+
+        for (iPtrByte = 0; iPtrByte < sizeof(ui32Priority); iPtrByte++)
+        {
+            pDst[iPtrByte] = pSrc[iPtrByte];
+        }
+    }
+    return PVRSRV_OK;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_
+{
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+	PVRSRV_KERNEL_MEM_INFO *psHW2DContextMemInfo;
+	IMG_HANDLE hBlockAlloc;
+	PRESMAN_ITEM psResItem;
+	IMG_BOOL bCleanupTimerRunning;
+	IMG_PVOID pvTimeData;
+} SGX_HW_2D_CONTEXT_CLEANUP;
+
+static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID  pvParam,
+												  IMG_UINT32 ui32Param,
+												  IMG_BOOL   bForceCleanup)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_2D_CONTEXT_CLEANUP *psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)pvParam;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+    /* First, ensure the context is no longer being utilised */
+    eError = SGXCleanupRequest(psCleanup->psDeviceNode,
+					  &psCleanup->psHW2DContextMemInfo->sDevVAddr,
+					  PVRSRV_CLEANUPCMD_2DC,
+					  bForceCleanup);
+
+	if (eError == PVRSRV_ERROR_RETRY)
+	{
+		if (!psCleanup->bCleanupTimerRunning)
+		{
+			OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+			psCleanup->bCleanupTimerRunning = IMG_TRUE;
+		}
+		else
+		{
+			if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+			{
+				eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+				psCleanup->bCleanupTimerRunning = IMG_FALSE;
+				OSTimeDestroy(psCleanup->pvTimeData);
+			}
+		}
+	}
+	else
+	{
+		if (psCleanup->bCleanupTimerRunning)
+		{
+			OSTimeDestroy(psCleanup->pvTimeData);
+		}
+	}
+
+	if (eError != PVRSRV_ERROR_RETRY)
+	{
+	    /* Free the Device Mem allocated */
+	    PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+	            psCleanup->psHW2DContextMemInfo);
+	
+	    /* Finally, free the cleanup structure itself */
+	    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				  sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+				  psCleanup,
+				  psCleanup->hBlockAlloc);
+	                  /*not nulling pointer, copy on stack*/
+	}
+	return eError;
+}
+
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE				hDeviceNode,
+                                    IMG_CPU_VIRTADDR        *psHW2DContextCpuVAddr,
+                                    IMG_UINT32              ui32HW2DContextSize,
+                                    IMG_UINT32              ui32OffsetToPDDevPAddr,
+                                    IMG_HANDLE              hDevMemContext,
+                                    IMG_DEV_VIRTADDR        *psHW2DContextDevVAddr,
+									PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+    PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)hDeviceNode;
+	DEVICE_MEMORY_INFO	*psDevMemoryInfo;
+    DEVICE_MEMORY_HEAP_INFO *psHeapInfo;
+    IMG_HANDLE hDevMemContextInt;
+    MMU_CONTEXT *psMMUContext;
+    IMG_DEV_PHYADDR sPDDevPAddr;
+    int iPtrByte;
+    IMG_UINT8 *pSrc;
+    IMG_UINT8 *pDst;
+	PRESMAN_ITEM psResItem;
+	IMG_UINT32 ui32PDDevPAddrInDirListFormat;
+	IMG_UINT8 *pStartPDDevPAddr, *pEndPDDevPAddr;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+						sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+						(IMG_VOID **)&psCleanup,
+						&hBlockAlloc,
+						"SGX Hardware 2D Context Cleanup");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate memory for SGX_HW_2D_CONTEXT_CLEANUP structure"));
+		goto exit0;
+	}
+
+	psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+    psHeapInfo = &psDevMemoryInfo->psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID];
+
+    eError = PVRSRVAllocDeviceMemKM(hDeviceNode,
+                               psPerProc,
+                               psHeapInfo->hDevMemHeap,
+                               PVRSRV_MEM_READ | PVRSRV_MEM_WRITE 
+                                 | PVRSRV_MEM_NO_SYNCOBJ | PVRSRV_MEM_EDM_PROTECT 
+                                 | PVRSRV_MEM_CACHE_CONSISTENT,
+                               ui32HW2DContextSize,
+                               32,
+                               IMG_NULL,
+                               0,
+                               0,0,0,IMG_NULL,	/* No sparse mapping data */
+                               &psCleanup->psHW2DContextMemInfo,
+                               "HW 2D Context");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate device memory for HW Render Context"));
+		goto exit1;
+	}
+
+	/* Ensure that the offset of Page directory dev physical address field is within the allocated context memory */
+	pStartPDDevPAddr = (IMG_UINT8 *)(psCleanup->psHW2DContextMemInfo->pvLinAddrKM) + ui32OffsetToPDDevPAddr;
+	pEndPDDevPAddr = pStartPDDevPAddr + sizeof(ui32PDDevPAddrInDirListFormat) - 1;
+
+	if (pStartPDDevPAddr < (IMG_UINT8 *)psCleanup->psHW2DContextMemInfo->pvLinAddrKM || 
+			pEndPDDevPAddr >= (IMG_UINT8 *)(psCleanup->psHW2DContextMemInfo->pvLinAddrKM) + ui32HW2DContextSize)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Offset of page directory device physical address is invalid"));
+		goto exit2;
+	}
+
+    eError = OSCopyFromUser(psPerProc,
+                            psCleanup->psHW2DContextMemInfo->pvLinAddrKM,
+                            psHW2DContextCpuVAddr,
+                            ui32HW2DContextSize);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't copy user-mode copy of HWContext into device memory"));
+		goto exit2;
+	}
+ 
+    /* Pass the DevVAddr of the new context back up through the bridge */
+    psHW2DContextDevVAddr->uiAddr = psCleanup->psHW2DContextMemInfo->sDevVAddr.uiAddr;
+
+    /* Retrieve the PDDevPAddr */
+    eError = PVRSRVLookupHandle(psPerProc->psHandleBase, 
+                           &hDevMemContextInt,
+                           hDevMemContext,
+                           PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+    if (eError != PVRSRV_OK)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Can't lookup DevMem Context"));
+        goto exit2;
+    }
+
+    psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
+    sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
+
+	/* 
+	   The PDDevPAddr needs to be shifted-down, as the uKernel expects it in the
+	   format it will be inserted into the DirList registers in.
+	*/
+	ui32PDDevPAddrInDirListFormat = sPDDevPAddr.uiAddr >> SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+    /* 
+       patch-in the Page-Directory Device-Physical address. Note that this is
+       copied-in one byte at a time, as we have no guarantee that the usermode-
+       provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+       current CPU architecture.
+     */
+	pSrc = (IMG_UINT8 *)&ui32PDDevPAddrInDirListFormat;
+    pDst = (IMG_UINT8 *)psCleanup->psHW2DContextMemInfo->pvLinAddrKM;
+    pDst += ui32OffsetToPDDevPAddr;
+
+    for (iPtrByte = 0; iPtrByte < sizeof(ui32PDDevPAddrInDirListFormat); iPtrByte++)
+    {
+        pDst[iPtrByte] = pSrc[iPtrByte];
+    }
+
+#if defined(PDUMP)
+    /* PDUMP the HW 2D Context */
+	PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW 2D context struct");
+
+	PDUMPMEM(
+        IMG_NULL, 
+        psCleanup->psHW2DContextMemInfo,
+        0, 
+        ui32HW2DContextSize, 
+        PDUMP_FLAGS_CONTINUOUS, 
+        MAKEUNIQUETAG(psCleanup->psHW2DContextMemInfo));
+
+    /* PDUMP the PDDevPAddr */
+	PDUMPCOMMENT("Page directory address in HW 2D transfer context");
+    PDUMPPDDEVPADDR(
+            psCleanup->psHW2DContextMemInfo,
+            ui32OffsetToPDDevPAddr,
+            sPDDevPAddr,
+            MAKEUNIQUETAG(psCleanup->psHW2DContextMemInfo),
+            PDUMP_PD_UNIQUETAG);
+#endif
+
+	psCleanup->hBlockAlloc = hBlockAlloc;
+	psCleanup->psDeviceNode = psDeviceNode;
+	psCleanup->bCleanupTimerRunning = IMG_FALSE;
+
+	psResItem = ResManRegisterRes(psPerProc->hResManContext,
+								  RESMAN_TYPE_HW_2D_CONTEXT,
+								  psCleanup,
+								  0,
+								  &SGXCleanupHW2DContextCallback);
+
+	if (psResItem == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: ResManRegisterRes failed"));
+        goto exit2;
+	}
+
+	psCleanup->psResItem = psResItem;
+
+	return (IMG_HANDLE)psCleanup;
+
+/* Error exit paths */
+exit2:
+    PVRSRVFreeDeviceMemKM(hDeviceNode,
+                         psCleanup->psHW2DContextMemInfo);
+exit1:
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+              sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+              psCleanup,
+              psCleanup->hBlockAlloc);
+    /*not nulling pointer, out of scope*/
+exit0:
+    return IMG_NULL;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext, IMG_BOOL bForceCleanup)
+{
+	PVRSRV_ERROR eError;
+	SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+
+	PVR_ASSERT(hHW2DContext != IMG_NULL);
+
+	if (hHW2DContext == IMG_NULL)
+	{
+		return (PVRSRV_ERROR_INVALID_PARAMS);
+	}
+
+	psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)hHW2DContext;
+
+	eError = ResManFreeResByPtr(psCleanup->psResItem, bForceCleanup);
+
+	return eError;
+}
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE)*/
+
+/*!****************************************************************************
+ @Function	SGX2DQuerySyncOpsCompleteKM
+
+ @Input		psSyncInfo : Sync object to be queried
+
+ @Return	IMG_TRUE - ops complete, IMG_FALSE - ops pending
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DQuerySyncOpsComplete)
+#endif
+static INLINE
+IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO	*psSyncInfo,
+								   IMG_UINT32				ui32ReadOpsPending,
+								   IMG_UINT32				ui32WriteOpsPending)
+{
+	PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+	return (IMG_BOOL)(
+					  (psSyncData->ui32ReadOpsComplete >= ui32ReadOpsPending) &&
+					  (psSyncData->ui32WriteOpsComplete >= ui32WriteOpsPending)
+					 );
+}
+
+/*!****************************************************************************
+ @Function	SGX2DQueryBlitsCompleteKM
+
+ @Input		psDevInfo : SGX device info structure
+
+ @Input		psSyncInfo : Sync object to be queried
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO	*psDevInfo,
+									   PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+									   IMG_BOOL bWaitForComplete)
+{
+	IMG_UINT32	ui32ReadOpsPending, ui32WriteOpsPending;
+
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+	PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+	ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+	ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+	if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+	{
+		/* Instant success */
+		PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
+		return PVRSRV_OK;
+	}
+
+	/* Not complete yet */
+	if (!bWaitForComplete)
+	{
+		/* Just report not complete */
+		PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
+		return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+	}
+
+	/* Start polling */
+	PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
+
+	LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+	{
+		OSSleepms(1);
+
+		if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+		{
+			/* Success */
+			PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over.  Blits complete."));
+			return PVRSRV_OK;
+		}
+
+		OSSleepms(1);
+	} END_LOOP_UNTIL_TIMEOUT();
+
+	/* Timed out */
+	PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+	{
+		PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+		PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: 0x%p, Syncdata: 0x%p",
+				psSyncInfo, psSyncData));
+
+		PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending));
+		PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending));
+
+	}
+#endif
+
+	return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXFlushHWRenderTargetKM(IMG_HANDLE psDeviceNode,
+									  IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr,
+									  IMG_BOOL bForceCleanup)
+{
+	PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr != IMG_NULL);
+
+	return SGXCleanupRequest(psDeviceNode,
+					  &sHWRTDataSetDevVAddr,
+					  PVRSRV_CLEANUPCMD_RT,
+					  bForceCleanup);
+}
+
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							   IMG_UINT32			ui32TimeWraps,
+							   IMG_UINT32			ui32Time)
+{
+#if defined(EUR_CR_TIMER)
+	PVR_UNREFERENCED_PARAMETER(psDevInfo);
+	PVR_UNREFERENCED_PARAMETER(ui32TimeWraps);
+	return ui32Time;
+#else
+	IMG_UINT64	ui64Clocks;
+	IMG_UINT32	ui32Clocksx16;
+
+	ui64Clocks = ((IMG_UINT64)ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
+					(psDevInfo->ui32uKernelTimerClock - (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
+	ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
+
+	return ui32Clocksx16;
+#endif /* EUR_CR_TIMER */
+}
+
+
+IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO	*psDevInfo,
+					   IMG_UINT32			ui32SGXClocks)
+{
+	/*
+		Round up to the next microsecond.
+	*/
+	OSWaitus(1 + (ui32SGXClocks * 1000000 / psDevInfo->ui32CoreClockSpeed));
+}
+
+
+
+/******************************************************************************
+ End of file (sgxutils.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxutils.h b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxutils.h
new file mode 100644
index 0000000..fc2ef6f
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/devices/sgx/sgxutils.h
@@ -0,0 +1,195 @@
+/*************************************************************************/ /*!
+@Title          Device specific utility routines declarations
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Inline functions/structures specific to SGX
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "perproc.h"
+#include "sgxinfokm.h"
+
+/* PRQA S 3410 7 */ /* macros require the absence of some brackets */
+#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
+	((sizeof(type) <= (psCCBMemInfo)->uAllocSize) && \
+	((psCCBKick)->offset <= (psCCBMemInfo)->uAllocSize - sizeof(type)))
+
+#define	CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \
+	((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
+		(psCCBKick)->offset))
+
+extern IMG_UINT64 ui64KickCount;
+
+
+IMG_IMPORT
+IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE	*psDeviceNode,
+								 IMG_UINT32			ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE	*psDeviceNode,
+								   SGXMKIF_CMD_TYPE		eCommandType,
+								   SGXMKIF_COMMAND		*psCommandData,
+								   IMG_UINT32			ui32CallerID,
+								   IMG_UINT32			ui32PDumpFlags,
+								   IMG_HANDLE			hDevMemContext,
+								   IMG_BOOL				bLastInScene);
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE		*psDeviceNode,
+									 SGXMKIF_CMD_TYPE		eCommandType,
+									 SGXMKIF_COMMAND		*psCommandData,
+									 IMG_UINT32				ui32CallerID,
+									 IMG_UINT32				ui32PDumpFlags,
+									 IMG_HANDLE				hDevMemContext,
+									 IMG_BOOL				bLastInScene);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE				psDeviceNode,
+                                        IMG_CPU_VIRTADDR        *psHWRenderContextCpuVAddr,
+                                        IMG_UINT32              ui32HWRenderContextSize,
+                                        IMG_UINT32              ui32OffsetToPDDevPAddr,
+                                        IMG_HANDLE              hDevMemContext,
+                                        IMG_DEV_VIRTADDR        *psHWRenderContextDevVAddr,
+										PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE		      psDeviceNode,
+                                          IMG_CPU_VIRTADDR        *psHWTransferContextCpuVAddr,
+                                          IMG_UINT32              ui32HWTransferContextSize,
+                                          IMG_UINT32              ui32OffsetToPDDevPAddr,
+                                          IMG_HANDLE              hDevMemContext,
+                                          IMG_DEV_VIRTADDR        *psHWTransferContextDevVAddr,
+										  PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXFlushHWRenderTargetKM(IMG_HANDLE psSGXDevInfo,
+									  IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr,
+									  IMG_BOOL bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext, IMG_BOOL bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext, IMG_BOOL bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSetRenderContextPriorityKM(IMG_HANDLE       hDeviceNode,
+                                           IMG_HANDLE       hHWRenderContext,
+                                           IMG_UINT32       ui32Priority,
+                                           IMG_UINT32       ui32OffsetOfPriorityField);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSetTransferContextPriorityKM(IMG_HANDLE       hDeviceNode,
+                                             IMG_HANDLE       hHWTransferContext,
+                                             IMG_UINT32       ui32Priority,
+                                             IMG_UINT32       ui32OffsetOfPriorityField);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE				psDeviceNode,
+                                    IMG_CPU_VIRTADDR        *psHW2DContextCpuVAddr,
+                                    IMG_UINT32              ui32HW2DContextSize,
+                                    IMG_UINT32              ui32OffsetToPDDevPAddr,
+                                    IMG_HANDLE              hDevMemContext,
+                                    IMG_DEV_VIRTADDR        *psHW2DContextDevVAddr,
+									PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext, IMG_BOOL bForceCleanup);
+#endif
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO	*psDevInfo,
+							   IMG_UINT32			ui32TimeWraps,
+							   IMG_UINT32			ui32Time);
+
+/*!
+*******************************************************************************
+
+ @Function	SGXWaitClocks
+
+ @Description
+
+ Wait for a specified number of SGX clock cycles to elapse.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32SGXClocks - number of clock cycles to wait
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO	*psDevInfo,
+					   IMG_UINT32			ui32SGXClocks);
+
+PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE	*psDeviceNode,
+							IMG_DEV_VIRTADDR	*psHWDataDevVAddr,
+							IMG_UINT32			ui32CleanupType,
+							IMG_BOOL			bForceCleanup);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetSGXRevDataKM(PVRSRV_DEVICE_NODE* psDeviceNode, IMG_UINT32 *pui32SGXCoreRev,
+				IMG_UINT32 *pui32SGXCoreID);
+
+/*!
+******************************************************************************
+
+ @Function	SGXContextSuspend
+
+ @Description - Interface to the SGX microkernel to instruct it to suspend or
+				resume processing on a given context. This will interrupt current
+				processing of this context if a task is already running and is
+				interruptable.
+
+ @Input psDeviceNode			SGX device node
+ @Input psHWContextDevVAddr		SGX virtual address of the context to be suspended
+								or resumed. Can be of type SGXMKIF_HWRENDERCONTEXT,
+								SGXMKIF_HWTRANSFERCONTEXT or SGXMKIF_HW2DCONTEXT
+ @Input bResume					IMG_TRUE to put a context into suspend state,
+								IMG_FALSE to resume a previously suspended context
+
+******************************************************************************/
+PVRSRV_ERROR SGXContextSuspend(PVRSRV_DEVICE_NODE	*psDeviceNode,
+							   IMG_DEV_VIRTADDR		*psHWContextDevVAddr,
+							   IMG_BOOL				bResume);
+
+/******************************************************************************
+ End of file (sgxutils.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk b/drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk
new file mode 100644
index 0000000..53aad07
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/Kbuild.mk
@@ -0,0 +1,194 @@
+########################################################################### ###
+#@Copyright     Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License       Dual MIT/GPLv2
+# 
+# The contents of this file are subject to the MIT license as set out below.
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+# 
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+# 
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+# 
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
+
+pvrsrvkm-y += \
+	services4/srvkm/env/linux/osfunc.o \
+	services4/srvkm/env/linux/mutils.o \
+	services4/srvkm/env/linux/mmap.o \
+	services4/srvkm/env/linux/module.o \
+	services4/srvkm/env/linux/pdump.o \
+	services4/srvkm/env/linux/proc.o \
+	services4/srvkm/env/linux/pvr_bridge_k.o \
+	services4/srvkm/env/linux/pvr_debug.o \
+	services4/srvkm/env/linux/mm.o \
+	services4/srvkm/env/linux/mutex.o \
+	services4/srvkm/env/linux/event.o \
+	services4/srvkm/env/linux/osperproc.o \
+	services4/srvkm/common/buffer_manager.o \
+	services4/srvkm/common/devicemem.o \
+	services4/srvkm/common/handle.o \
+	services4/srvkm/common/hash.o \
+	services4/srvkm/common/lists.o \
+	services4/srvkm/common/mem.o \
+	services4/srvkm/common/mem_debug.o \
+	services4/srvkm/common/metrics.o \
+	services4/srvkm/common/osfunc_common.o \
+	services4/srvkm/common/pdump_common.o \
+	services4/srvkm/common/perproc.o \
+	services4/srvkm/common/power.o \
+	services4/srvkm/common/pvrsrv.o \
+	services4/srvkm/common/ra.o \
+	services4/srvkm/common/refcount.o \
+	services4/srvkm/common/resman.o \
+	services4/srvkm/bridged/bridged_support.o \
+	services4/srvkm/bridged/bridged_pvr_bridge.o \
+	services4/system/$(PVR_SYSTEM)/sysconfig.o \
+	services4/system/$(PVR_SYSTEM)/sysutils.o
+
+ifeq ($(SUPPORT_PVRSRV_DEVICE_CLASS),1)
+pvrsrvkm-y += \
+	services4/srvkm/common/deviceclass.o \
+	services4/srvkm/common/queue.o
+endif
+
+ifeq ($(SUPPORT_ION),1)
+pvrsrvkm-y += \
+	services4/srvkm/env/linux/ion.o
+ifeq ($(LMA),1)
+pvrsrvkm-y += \
+	services4/srvkm/env/linux/lma_heap_ion.o 
+endif
+endif
+
+ifeq ($(SUPPORT_DMABUF),1)
+pvrsrvkm-y += \
+	services4/srvkm/env/linux/dmabuf.o \
+	services4/srvkm/env/linux/pvr_linux_fence.o
+endif
+
+ifeq ($(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC),1)
+pvrsrvkm-y += \
+	services4/srvkm/env/linux/pvr_sync.o \
+	services4/srvkm/env/linux/pvr_sync_common.o
+endif
+
+ifeq ($(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE),1)
+pvrsrvkm-y += \
+	services4/srvkm/env/linux/pvr_sync_common.o \
+	services4/srvkm/env/linux/pvr_fence.o \
+	services4/srvkm/env/linux/dma_fence_sync_native_server.o \
+	services4/srvkm/env/linux/pvr_counting_timeline.o \
+	services4/srvkm/env/linux/pvr_sw_fence.o
+endif
+
+ifeq ($(TTRACE),1)
+pvrsrvkm-y += \
+	services4/srvkm/common/ttrace.o
+endif
+
+ifeq ($(SUPPORT_PVRSRV_ANDROID_SYSTRACE),1)
+pvrsrvkm-y += \
+	services4/srvkm/env/linux/systrace.o
+endif
+
+ifneq ($(W),1)
+CFLAGS_osfunc.o := -Werror
+CFLAGS_mutils.o := -Werror
+CFLAGS_mmap.o := -Werror
+CFLAGS_module.o := -Werror
+CFLAGS_pdump.o := -Werror
+CFLAGS_proc.o := -Werror
+CFLAGS_pvr_bridge_k.o := -Werror
+CFLAGS_pvr_debug.o := -Werror
+CFLAGS_mm.o := -Werror
+CFLAGS_mutex.o := -Werror
+CFLAGS_event.o := -Werror
+CFLAGS_osperproc.o := -Werror
+CFLAGS_buffer_manager.o := -Werror
+CFLAGS_devicemem.o := -Werror
+CFLAGS_deviceclass.o := -Werror
+CFLAGS_handle.o := -Werror
+CFLAGS_hash.o := -Werror
+CFLAGS_metrics.o := -Werror
+CFLAGS_pvrsrv.o := -Werror
+CFLAGS_queue.o := -Werror
+CFLAGS_ra.o := -Werror
+CFLAGS_resman.o := -Werror
+CFLAGS_power.o := -Werror
+CFLAGS_mem.o := -Werror
+CFLAGS_pdump_common.o := -Werror
+CFLAGS_bridged_support.o := -Werror
+CFLAGS_bridged_pvr_bridge.o := -Werror
+CFLAGS_perproc.o := -Werror
+CFLAGS_lists.o := -Werror
+CFLAGS_mem_debug.o := -Werror
+CFLAGS_osfunc_common.o := -Werror
+CFLAGS_refcount.o := -Werror
+endif
+
+# SUPPORT_SGX==1 only
+
+pvrsrvkm-y += \
+	services4/srvkm/bridged/sgx/bridged_sgx_bridge.o \
+	services4/srvkm/devices/sgx/sgxinit.o \
+	services4/srvkm/devices/sgx/sgxpower.o \
+	services4/srvkm/devices/sgx/sgxreset.o \
+	services4/srvkm/devices/sgx/sgxutils.o \
+	services4/srvkm/devices/sgx/sgxkick.o \
+	services4/srvkm/devices/sgx/sgxtransfer.o \
+	services4/srvkm/devices/sgx/mmu.o \
+	services4/srvkm/devices/sgx/pb.o
+
+ifneq ($(W),1)
+CFLAGS_bridged_sgx_bridge.o := -Werror
+CFLAGS_sgxinit.o := -Werror
+CFLAGS_sgxpower.o := -Werror
+CFLAGS_sgxreset.o := -Werror
+CFLAGS_sgxutils.o := -Werror
+CFLAGS_sgxkick.o := -Werror
+CFLAGS_sgxtransfer.o := -Werror
+CFLAGS_mmu.o := -Werror
+CFLAGS_pb.o := -Werror
+endif
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+
+pvrsrvkm-y += \
+ services4/srvkm/env/linux/pvr_drm.o
+
+ccflags-y += \
+ -Iinclude/drm \
+ -I$(TOP)/services4/include/env/linux \
+
+ifeq ($(PVR_DRI_DRM_NOT_PCI),1)
+ccflags-y += -I$(TOP)/services4/3rdparty/linux_drm
+endif
+
+endif # SUPPORT_DRI_DRM
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk b/drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk
new file mode 100644
index 0000000..535a1f9
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/Linux.mk
@@ -0,0 +1,45 @@
+########################################################################### ###
+#@Copyright     Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License       Dual MIT/GPLv2
+# 
+# The contents of this file are subject to the MIT license as set out below.
+# 
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+# 
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
+# 
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+# 
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+# 
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+### ###########################################################################
+
+modules := srvkm
+
+srvkm_type := kernel_module
+srvkm_target := pvrsrvkm.ko
+srvkm_makefile := $(THIS_DIR)/Kbuild.mk
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/dma_fence_sync_native_server.c b/drivers/gpu/pvr/services4/srvkm/env/linux/dma_fence_sync_native_server.c
new file mode 100644
index 0000000..b5cfe10
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/dma_fence_sync_native_server.c
@@ -0,0 +1,94 @@
+/*************************************************************************/ /*!
+@File           sync_native_server.c
+@Title          Native implementation of server fence sync interface.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    The server implementation of software native synchronisation.
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/sync_file.h>
+#include <linux/version.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "servicesext.h"
+#include "pvrsrv_sync_server.h"
+#include "pvr_fence.h"
+#include "pvr_counting_timeline.h"
+
+struct dma_fence* SyncSWTimelineFenceCreateKM(IMG_INT32 iSWTimeline,
+					 IMG_UINT32 ui32NextSyncPtValue,
+					 const IMG_CHAR *pszFenceName)
+{
+	PVRSRV_ERROR eError;
+	struct PVR_COUNTING_FENCE_TIMELINE *psSWTimeline;
+	struct dma_fence *psFence = NULL;
+
+	psSWTimeline = pvr_sync_get_sw_timeline(iSWTimeline);
+	if (!psSWTimeline)
+	{
+		/* unrecognised timeline */
+		PVR_DPF((PVR_DBG_ERROR, "%s: unrecognised timeline", __func__));
+		goto ErrorOut;
+	}
+
+	psFence = pvr_counting_fence_create(psSWTimeline, ui32NextSyncPtValue);
+	pvr_counting_fence_timeline_put(psSWTimeline);
+	if(!psFence)
+	{
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto ErrorPutFence;
+	}
+
+	return psFence;
+
+ErrorPutFence:
+	dma_fence_put(psFence);
+ErrorOut:
+	return IMG_NULL;
+}
+
+PVRSRV_ERROR SyncSWTimelineAdvanceKM(IMG_PVOID pvSWTimeline)
+{
+	pvr_counting_fence_timeline_inc(pvSWTimeline, 1);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SyncSWTimelineReleaseKM(IMG_PVOID pvSWTimeline)
+{
+	pvr_counting_fence_timeline_put(pvSWTimeline);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SyncSWTimelineFenceReleaseKM(IMG_PVOID pvSWFenceObj)
+{
+	dma_fence_put(pvSWFenceObj);
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SyncSWGetTimelineObj(IMG_INT32 i32SWTimeline, IMG_PVOID *ppvSWTimelineObj)
+{
+	struct PVR_COUNTING_FENCE_TIMELINE *psSwTimeline = pvr_sync_get_sw_timeline(i32SWTimeline);
+
+	if (psSwTimeline == NULL)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	*ppvSWTimelineObj = psSwTimeline;
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SyncSWGetFenceObj(IMG_INT32 i32SWFence, IMG_PVOID *ppvSWFenceObj)
+{
+	struct dma_fence *psFence = sync_file_get_fence(i32SWFence);
+
+	if(psFence == NULL)
+	{
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+	*ppvSWFenceObj = (IMG_PVOID*)psFence;
+	return PVRSRV_OK;
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/dmabuf.c b/drivers/gpu/pvr/services4/srvkm/env/linux/dmabuf.c
new file mode 100644
index 0000000..0051bff
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/dmabuf.c
@@ -0,0 +1,328 @@
+/*************************************************************************/ /*!
+@Title          Dma_buf support code.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "dmabuf.h"
+
+#if defined(SUPPORT_DMABUF)
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/dma-buf.h>
+#include <linux/scatterlist.h>
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "services_headers.h"
+#include "pvr_debug.h"
+#include "linkage.h"
+#include "pvr_bridge.h"
+
+struct dmabuf_import
+{
+	struct dma_buf *dma_buf;
+
+	struct dma_buf_attachment *attachment;
+
+	struct sg_table *sg_table;
+
+#if defined(PDUMP)
+	void *kvaddr;
+#endif /* defined(PDUMP) */
+};
+
+IMG_VOID DmaBufUnimportAndReleasePhysAddr(IMG_HANDLE hImport)
+{
+	struct dmabuf_import *import;
+
+	import = (struct dmabuf_import *)hImport;
+
+#if defined(PDUMP)
+	if (import->kvaddr)
+	{
+		dma_buf_vunmap(import->dma_buf, import->kvaddr);
+		dma_buf_end_cpu_access(import->dma_buf,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0))
+					0, import->dma_buf->size,
+#endif
+					DMA_BIDIRECTIONAL);
+	}
+#endif /* defined(PDUMP) */
+
+	if (!IS_ERR_OR_NULL(import->sg_table))
+	{
+		dma_buf_unmap_attachment(import->attachment,
+						import->sg_table,
+						DMA_BIDIRECTIONAL);
+	}
+
+	if (!IS_ERR_OR_NULL(import->attachment))
+	{
+		dma_buf_detach(import->dma_buf, import->attachment);
+	}
+
+	if (!IS_ERR_OR_NULL(import->dma_buf))
+	{
+		dma_buf_put(import->dma_buf);
+	}
+
+	kfree(import);
+}
+
+PVRSRV_ERROR DmaBufImportAndAcquirePhysAddr(const IMG_INT32 i32FD,
+											const IMG_SIZE_T uiDmaBufOffset,
+											const IMG_SIZE_T uiSize,
+											IMG_UINT32 *pui32PageCount,
+											IMG_SYS_PHYADDR **ppsSysPhysAddr,
+											IMG_SIZE_T *puiMemInfoOffset,
+											IMG_PVOID  *ppvKernAddr,
+											IMG_HANDLE *phImport,
+											IMG_HANDLE *phUnique)
+{
+	struct dmabuf_import *import = NULL;
+	struct device *dev = NULL;
+	struct scatterlist *sg;
+	size_t buf_size;
+	size_t start_offset, end_offset, buf_offset, remainder;
+	unsigned npages = 0;
+	unsigned pti = 0;
+	IMG_SYS_PHYADDR *spaddr = NULL;
+	unsigned i;
+	PVRSRV_ERROR eError = PVRSRV_ERROR_INVALID_PARAMS;
+#if defined(PDUMP)
+	int err;
+#endif	/* defined(PDUMP) */
+
+	import = kzalloc(sizeof(*import), GFP_KERNEL);
+	if (!import)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Out of memory", __func__));
+		eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto error;
+	}
+
+	dev = PVRLDMGetDevice();
+	if (!dev)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't get device", __func__));
+		eError = PVRSRV_ERROR_NOT_SUPPORTED;
+		goto error;
+	}
+
+	import->dma_buf = dma_buf_get((int)i32FD);
+	if (IS_ERR(import->dma_buf))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: dma_buf_get failed: %ld", __func__, PTR_ERR(import->dma_buf)));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto error;
+	}
+
+	buf_size = uiSize ? uiSize : import->dma_buf->size;
+
+	if ((uiDmaBufOffset + buf_size) > import->dma_buf->size ||
+		(size_t)(uiDmaBufOffset + buf_size) < buf_size)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Bad size and/or offset for FD", __func__));
+		eError = PVRSRV_ERROR_INVALID_PARAMS;
+		goto error;
+	}
+
+	import->attachment = dma_buf_attach(import->dma_buf, dev);
+	if (IS_ERR(import->attachment))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: dma_buf_attach failed: %ld", __func__, PTR_ERR(import->attachment)));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto error;
+	}
+
+	import->sg_table = dma_buf_map_attachment(import->attachment,
+							DMA_BIDIRECTIONAL);
+	if (IS_ERR(import->sg_table))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: dma_buf_map_attachment failed: %ld", __func__, PTR_ERR(import->sg_table)));
+		eError = PVRSRV_ERROR_BAD_MAPPING;
+		goto error;
+	}
+
+	start_offset = PAGE_MASK & uiDmaBufOffset;
+	end_offset = PAGE_ALIGN(uiDmaBufOffset + buf_size);
+
+	*puiMemInfoOffset = (uiDmaBufOffset - start_offset);
+
+	npages = (end_offset - start_offset) >> PAGE_SHIFT;
+
+	/* The following allocation will be freed by the caller */
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+					npages * sizeof(IMG_SYS_PHYADDR),
+					(IMG_VOID **)&spaddr, IMG_NULL,
+					"Array of Page Addresses");
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed: %s", __func__, PVRSRVGetErrorStringKM(eError)));
+		goto error;
+	}
+
+	buf_offset = 0;
+	remainder = buf_size;
+	start_offset = PAGE_MASK & uiDmaBufOffset;
+	end_offset = PAGE_ALIGN(uiDmaBufOffset + buf_size);
+
+	for_each_sg(import->sg_table->sgl, sg, import->sg_table->nents, i)
+	{
+		if (buf_offset >= end_offset)
+		{
+			break;
+		}
+
+		if ((start_offset >= buf_offset) && (start_offset < buf_offset + sg_dma_len(sg)))
+		{
+			size_t sg_start;
+			size_t sg_pos;
+			size_t sg_remainder;
+
+			sg_start = start_offset - buf_offset;
+
+			sg_remainder = MIN(sg_dma_len(sg) - sg_start, remainder);
+
+			for (sg_pos = sg_start; sg_pos < sg_start + sg_remainder; sg_pos += PAGE_SIZE)
+			{
+				IMG_CPU_PHYADDR cpaddr;
+
+				cpaddr.uiAddr = PAGE_MASK & (sg_phys(sg) + sg_pos);
+				BUG_ON(pti >= npages);
+
+				spaddr[pti++] = SysCpuPAddrToSysPAddr(cpaddr);
+			}
+
+			remainder -= sg_remainder;
+			buf_offset += sg_dma_len(sg);
+			start_offset = buf_offset;
+		}
+		else
+		{
+			buf_offset += sg_dma_len(sg);
+		}
+	}
+	BUG_ON(remainder);
+
+#if defined(PDUMP)
+	err = dma_buf_begin_cpu_access(import->dma_buf,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0))
+					0, import->dma_buf->size,
+#endif
+					DMA_BIDIRECTIONAL);
+	if (err)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "%s: dma_buf_begin_cpu_access failed: %d", __func__, err));
+	}
+	else
+	{
+		import->kvaddr = dma_buf_vmap(import->dma_buf);
+		*ppvKernAddr = import->kvaddr;
+	}
+#else	/* defined(PDUMP) */
+	*ppvKernAddr = NULL;
+#endif	/* defined(PDUMP) */
+
+	*pui32PageCount = pti;
+	*ppsSysPhysAddr = spaddr;
+	*phImport = (IMG_HANDLE)import;
+	*phUnique = (IMG_HANDLE)import->dma_buf;
+
+	return PVRSRV_OK;
+error:
+	if (import)
+	{
+		DmaBufUnimportAndReleasePhysAddr((IMG_HANDLE)import);
+	}
+
+	if (spaddr)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+				npages * sizeof(IMG_SYS_PHYADDR),
+				(IMG_VOID **)&spaddr, IMG_NULL);
+	}
+
+	return eError;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
+IMG_HANDLE DmaBufGetNativeSyncHandle(IMG_HANDLE hImport)
+{
+	struct dmabuf_import *import;
+	struct dmabuf_resvinfo *info;
+
+	import = (struct dmabuf_import *)hImport;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+	if (info)
+	{
+		info->resv = import->dma_buf->resv;
+	}
+
+	return (IMG_HANDLE)info;
+}
+
+void DmaBufFreeNativeSyncHandle(IMG_HANDLE hSync)
+{
+	struct dmabuf_resvinfo *info;
+
+	info = (struct dmabuf_resvinfo *)hSync;
+
+	kfree(info);
+}
+#else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) */
+IMG_HANDLE DmaBufGetNativeSyncHandle(IMG_HANDLE hImport)
+{
+	(void) hImport;
+
+	return IMG_NULL;
+}
+
+void DmaBufFreeNativeSyncHandle(IMG_HANDLE hSync)
+{
+	(void) hSync;
+}
+#endif	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) */
+
+#endif /* defined(SUPPORT_DMABUF) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/dmabuf.h b/drivers/gpu/pvr/services4/srvkm/env/linux/dmabuf.h
new file mode 100644
index 0000000..9a09464
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/dmabuf.h
@@ -0,0 +1,98 @@
+/*************************************************************************/ /*!
+@Title          DmaBuf driver inter-operability code.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __IMG_LINUX_DMABUF_H__
+#define __IMG_LINUX_DMABUF_H__
+
+#if defined(SUPPORT_DMABUF)
+
+#include <linux/version.h>
+
+#include "img_types.h"
+#include "servicesext.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
+#include <linux/reservation.h>
+#include "pvr_bridge.h"
+
+struct dmabuf_resvinfo
+{
+	struct reservation_object *resv;
+};
+
+static inline void *DmaBufGetReservationObject(IMG_HANDLE hSync)
+{
+	struct dmabuf_resvinfo *info;
+
+	info = (struct dmabuf_resvinfo *)hSync;
+
+	return info->resv;
+}
+#else
+static inline void *DmaBufGetReservationObject(IMG_HANDLE hSync)
+{
+	(void) hSync;
+
+	return (void *)0;
+}
+#endif
+
+PVRSRV_ERROR DmaBufInit(IMG_VOID);
+
+IMG_VOID DmaBufDeinit(IMG_VOID);
+
+PVRSRV_ERROR DmaBufImportAndAcquirePhysAddr(const IMG_INT32 i32DmaBufFD,
+											const IMG_SIZE_T uiDmaBufOffset,
+											const IMG_SIZE_T uiSize,
+											IMG_UINT32 *pui32PageCount,
+											IMG_SYS_PHYADDR **ppsSysPhysAddr,
+											IMG_SIZE_T *puiMemInfoOffset,
+											IMG_PVOID *ppvKernAddr,
+											IMG_HANDLE *phImport,
+											IMG_HANDLE *phUnique);
+
+IMG_VOID DmaBufUnimportAndReleasePhysAddr(IMG_HANDLE hImport);
+
+IMG_HANDLE DmaBufGetNativeSyncHandle(IMG_HANDLE hImport);
+void DmaBufFreeNativeSyncHandle(IMG_HANDLE hSync);
+#endif /* defined(SUPPORT_DMABUF) */
+
+#endif /* __IMG_LINUX_DMABUF_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h b/drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h
new file mode 100644
index 0000000..b838809
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/env_data.h
@@ -0,0 +1,93 @@
+/*************************************************************************/ /*!
+@Title          Environmental Data header file
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Linux-specific part of system data.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+/* 
+ *	Env data specific to linux - convenient place to put this
+ */
+
+/* Fairly arbitrary sizes - hopefully enough for all bridge calls */
+#define PVRSRV_MAX_BRIDGE_IN_SIZE	0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE	0x1000
+
+typedef	struct _PVR_PCI_DEV_TAG
+{
+	struct pci_dev		*psPCIDev;
+	HOST_PCI_INIT_FLAGS	ePCIFlags;
+	IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+	IMG_VOID		*pvBridgeData;
+	struct pm_dev		*psPowerDevice;
+	IMG_BOOL		bLISRInstalled;
+	IMG_BOOL		bMISRInstalled;
+	IMG_UINT32		ui32IRQ;
+	IMG_VOID		*pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+	struct workqueue_struct	*psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+	struct work_struct	sMISRWork;
+	IMG_VOID		*pvMISRData;
+#else
+	struct tasklet_struct	sMISRTasklet;
+#endif
+#if defined (SUPPORT_ION)
+	IMG_HANDLE		hIonHeaps;
+	IMG_HANDLE		hIonDev;
+#endif
+} ENV_DATA;
+
+#endif /* _ENV_DATA_ */
+/*****************************************************************************
+ End of file (env_data.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h b/drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h
new file mode 100644
index 0000000..788e80f
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/env_perproc.h
@@ -0,0 +1,79 @@
+/*************************************************************************/ /*!
+@Title          OS specific per process data interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Linux per process data
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+
+#include "proc.h"
+#include "services.h"
+#include "handle.h"
+
+#define ION_CLIENT_NAME_SIZE	50
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+	IMG_HANDLE hBlockAlloc;
+	struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	struct list_head sDRMAuthListHead;
+#endif
+#if defined(SUPPORT_ION)
+ 	struct ion_client *psIONClient;
+	IMG_CHAR azIonClientName[ION_CLIENT_NAME_SIZE];
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+ 
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif /* __ENV_PERPROC_H__ */
+
+/******************************************************************************
+ End of file (env_perproc.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/event.c b/drivers/gpu/pvr/services4/srvkm/env/linux/event.c
new file mode 100644
index 0000000..c60f2d5
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/event.c
@@ -0,0 +1,413 @@
+/*************************************************************************/ /*!
+@Title          Event Object 
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/io.h>
+#include <asm/page.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+#include <asm/system.h>
+#endif
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "mutex.h"
+#include "lock.h"
+#include "event.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+   rwlock_t		sLock;
+   struct list_head	sList;
+   
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+   	atomic_t	sTimeStamp;
+   	IMG_UINT32  ui32TimeStampPrevious;
+#if defined(DEBUG)
+	IMG_UINT	ui32Stats;
+#endif
+    wait_queue_head_t sWait;	
+	struct list_head        sList;
+	IMG_HANDLE		hResItem;				
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+/*!
+******************************************************************************
+
+ @Function	LinuxEventObjectListCreate
+ 
+ @Description 
+ 
+ Linux wait object list creation
+
+ @Output    hOSEventKM : Pointer to the event object list handle 
+ 
+ @Return   PVRSRV_ERROR  :  Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList;
+
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), 
+		(IMG_VOID **)&psEventObjectList, IMG_NULL,
+		"Linux Event Object List") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));		
+		return PVRSRV_ERROR_OUT_OF_MEMORY;	
+	}
+
+	INIT_LIST_HEAD(&psEventObjectList->sList);
+
+	rwlock_init(&psEventObjectList->sLock);
+	
+	*phEventObjectList = (IMG_HANDLE *) psEventObjectList;
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	LinuxEventObjectListDestroy
+ 
+ @Description 
+ 
+ Linux wait object list destruction
+
+ @Input    hOSEventKM : Event object list handle 
+ 
+ @Return   PVRSRV_ERROR  :  Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+	if(psEventObjectList)	
+	{
+		IMG_BOOL bListEmpty;
+
+		read_lock(&psEventObjectList->sLock);
+		bListEmpty = list_empty(&psEventObjectList->sList);
+		read_unlock(&psEventObjectList->sLock);
+
+		if (!bListEmpty) 
+		{
+			 PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+			 return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+		}
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL);
+		/*not nulling pointer, copy on stack*/
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	LinuxEventObjectDelete
+ 
+ @Description 
+ 
+ Linux wait object removal
+ 
+ @Input    hOSEventObjectList : Event object list handle 
+ @Input    hOSEventObject : Event object handle 
+ @Input    bResManCallback : Called from the resman
+ 
+ @Return   PVRSRV_ERROR  :  Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+	if(hOSEventObjectList)
+	{
+		if(hOSEventObject)
+		{
+			PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject; 
+#if defined(DEBUG)
+			PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif
+			if(ResManFreeResByPtr(psLinuxEventObject->hResItem, CLEANUP_WITH_POLL) != PVRSRV_OK)
+			{
+				return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+			}
+			
+			return PVRSRV_OK;
+		}
+	}
+	return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+
+}
+
+/*!
+******************************************************************************
+
+ @Function	LinuxEventObjectDeleteCallback
+ 
+ @Description 
+ 
+ Linux wait object removal
+ 
+ @Input    hOSEventObject : Event object handle 
+ 
+ @Return   PVRSRV_ERROR  :  Error code
+
+******************************************************************************/
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup)
+{
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+	unsigned long ulLockFlags;
+
+	PVR_UNREFERENCED_PARAMETER(ui32Param);
+	PVR_UNREFERENCED_PARAMETER(bForceCleanup);
+
+	write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+	list_del(&psLinuxEventObject->sList);
+	write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+
+#if defined(DEBUG)
+	PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif	
+
+	OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+	return PVRSRV_OK;
+}
+/*!
+******************************************************************************
+
+ @Function	LinuxEventObjectAdd
+ 
+ @Description 
+ 
+ Linux wait object addition
+
+ @Input    hOSEventObjectList : Event object list handle 
+ @Output   phOSEventObject : Pointer to the event object handle 
+ 
+ @Return   PVRSRV_ERROR  :  Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject; 
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; 
+	IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+	unsigned long ulLockFlags;
+
+	psPerProc = PVRSRVPerProcessData(ui32PID);
+	if (psPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* allocate completion variable */
+	if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), 
+		(IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+		"Linux Event Object") != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));		
+		return PVRSRV_ERROR_OUT_OF_MEMORY;	
+	}
+	
+	INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+	atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+	psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+	psLinuxEventObject->ui32Stats = 0;
+#endif
+    init_waitqueue_head(&psLinuxEventObject->sWait);
+
+	psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+	psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+													 RESMAN_TYPE_EVENT_OBJECT,
+													 psLinuxEventObject,
+													 0,
+													 &LinuxEventObjectDeleteCallback);	
+
+	write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+	list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+	write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+	
+	*phOSEventObject = psLinuxEventObject;
+
+	return PVRSRV_OK;	 
+}
+
+/*!
+******************************************************************************
+
+ @Function	LinuxEventObjectSignal
+ 
+ @Description 
+ 
+ Linux wait object signaling function
+ 
+ @Input    hOSEventObjectList : Event object list handle 
+ 
+ @Return   PVRSRV_ERROR  :  Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+	PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList; 
+	struct list_head *psListEntry, *psList;
+
+	psList = &psLinuxEventObjectList->sList;
+
+	/*
+	 * We don't take the write lock in interrupt context, so we don't
+	 * need to use read_lock_irqsave.
+	 */
+	read_lock(&psLinuxEventObjectList->sLock);
+	list_for_each(psListEntry, psList) 
+	{       	
+
+		psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);	
+		
+		atomic_inc(&psLinuxEventObject->sTimeStamp);	
+	 	wake_up_interruptible(&psLinuxEventObject->sWait);
+	}
+	read_unlock(&psLinuxEventObjectList->sLock);
+
+	return 	PVRSRV_OK;
+  	
+}
+
+/*!
+******************************************************************************
+
+ @Function	LinuxEventObjectWait
+ 
+ @Description 
+ 
+ Linux wait object routine
+ 
+ @Input    hOSEventObject : Event object handle 
+ 
+ @Input   ui32MSTimeout : Time out value in msec
+
+ @Return   PVRSRV_ERROR  :  Error code
+
+******************************************************************************/
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+	IMG_UINT32 ui32TimeStamp;
+	DEFINE_WAIT(sWait);
+
+	PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+	IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+	
+	do	
+	{
+		prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+		ui32TimeStamp = (IMG_UINT32)atomic_read(&psLinuxEventObject->sTimeStamp);
+   	
+		if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+		{
+			break;
+		}
+
+		LinuxUnLockMutex(&gPVRSRVLock);		
+
+		ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+		
+		LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+#if defined(DEBUG)
+		psLinuxEventObject->ui32Stats++;
+#endif			
+
+		
+	} while (ui32TimeOutJiffies);
+
+	finish_wait(&psLinuxEventObject->sWait, &sWait);	
+
+	psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+	return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/event.h b/drivers/gpu/pvr/services4/srvkm/env/linux/event.h
new file mode 100644
index 0000000..5c1451c
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/event.h
@@ -0,0 +1,48 @@
+/*************************************************************************/ /*!
+@Title          Event Object 
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c
new file mode 100644
index 0000000..8d3ddfa
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.c
@@ -0,0 +1,580 @@
+/*************************************************************************/ /*!
+@Title          Ion driver inter-operability code.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "ion.h"
+
+/* Three possible configurations:
+ *
+ *  - SUPPORT_ION && CONFIG_ION_OMAP
+ *    Real ion support, but sharing with an SOC ion device. We need
+ *    to co-share the heaps too.
+ *
+ *  - SUPPORT_ION && !CONFIG_ION_OMAP
+ *    "Reference" ion implementation. Creates its own ion device
+ *    and heaps for the driver to use.
+ */
+
+#if defined(SUPPORT_ION)
+
+#include <linux/scatterlist.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#if defined(CONFIG_ION_OMAP)
+
+/* Real ion with sharing */
+
+extern struct ion_device *omap_ion_device;
+struct ion_device *gpsIonDev;
+
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+	gpsIonDev = omap_ion_device;
+	return PVRSRV_OK;
+}
+
+IMG_VOID IonDeinit(IMG_VOID)
+{
+	gpsIonDev = IMG_NULL;
+}
+
+#else /* defined(CONFIG_ION_OMAP) */
+
+#if defined(CONFIG_ION_S5P)
+
+/* Real ion with sharing (s5pv210) */
+
+extern struct ion_device *s5p_ion_device;
+struct ion_device *gpsIonDev;
+
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+	gpsIonDev = s5p_ion_device;
+	return PVRSRV_OK;
+}
+
+IMG_VOID IonDeinit(IMG_VOID)
+{
+	gpsIonDev = IMG_NULL;
+}
+
+#else /* defined(CONFIG_ION_S5P) */
+
+#if defined(CONFIG_ION_SUNXI)
+
+/* Real ion with sharing (sunxi) */
+
+extern struct ion_device *sunxi_ion_device;
+struct ion_device *gpsIonDev;
+
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+	gpsIonDev = sunxi_ion_device;
+	return PVRSRV_OK;
+}
+
+IMG_VOID IonDeinit(IMG_VOID)
+{
+	gpsIonDev = IMG_NULL;
+}
+
+#else /* defined(CONFIG_ION_SUNXI) */
+
+#if defined(CONFIG_ION_INCDHAD1)
+
+/* Real ion with sharing (incdhad1) */
+
+extern struct ion_device *incdhad1_ion_device;
+struct ion_device *gpsIonDev;
+
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+	gpsIonDev = incdhad1_ion_device;
+	return PVRSRV_OK;
+}
+
+
+IMG_VOID IonDeinit(IMG_VOID)
+{
+	gpsIonDev = IMG_NULL;
+}
+
+#else /* defined(CONFIG_ION_INCDHAD1) */
+
+/* "Reference" ion implementation */
+
+#include SUPPORT_ION_PRIV_HEADER
+#include <linux/version.h>
+#include "ion_sys_private.h"
+#include "lma_heap_ion.h"
+
+static struct ion_heap **gapsIonHeaps;
+struct ion_device *gpsIonDev;
+
+#if defined(LMA)
+struct ion_platform_data gsTCIonConfig = {
+        .nr = 1,
+        .heaps =
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,39))
+#else
+                (struct ion_platform_heap [])
+#endif
+                {
+                        {
+                                /* This heap must be first. The base address and size are filled
+                                   in from data passed down by sysconfig.c. */
+                                .type = ION_HEAP_TYPE_CUSTOM,
+                                .name = "tc_local_mem",
+                                .id = ION_HEAP_TYPE_CUSTOM,
+                                .base = 0,                      /* filled in later */
+                                .size = 0,                      /* filled in later */
+                        }
+                }
+};
+
+PVRSRV_ERROR IonInit(void *pvPrivateData)
+{
+        PVRSRV_ERROR eError = PVRSRV_OK;
+        int i;
+
+        ION_TC_PRIVATE_DATA sPrivateData = *(ION_TC_PRIVATE_DATA *)pvPrivateData;
+
+        /* Fill in the heap base and size according to the private data. */
+        gsTCIonConfig.heaps[0].base = sPrivateData.uiHeapBase;
+        gsTCIonConfig.heaps[0].size = sPrivateData.uiHeapSize;
+
+        gapsIonHeaps = kzalloc(sizeof(struct ion_heap *) * gsTCIonConfig.nr,
+                                                   GFP_KERNEL);
+        gpsIonDev = ion_device_create(NULL);
+        if (IS_ERR_OR_NULL(gpsIonDev))
+        {
+                kfree(gapsIonHeaps);
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+        }
+
+        for (i = 0; i < gsTCIonConfig.nr; i++)
+        {
+                struct ion_platform_heap *psPlatHeapData = &gsTCIonConfig.heaps[i];
+
+                switch (psPlatHeapData->type)
+                {
+                        case ION_HEAP_TYPE_CUSTOM:
+                                /* Custom heap: this is used to mean a TC-specific heap,
+                                   which allocates from local memory. */
+                                gapsIonHeaps[i] = lma_heap_create(psPlatHeapData);
+                                break;
+                        default:
+                                /* For any other type of heap, hand this to ion to create as
+                                   appropriate. We don't necessarily need any of these -
+                                   this just gives us the flexibility to have another kind
+                                   of heap if necessary. */
+                                gapsIonHeaps[i] = ion_heap_create(psPlatHeapData);
+                                break;
+                }
+
+                if (IS_ERR_OR_NULL(gapsIonHeaps[i]))
+                {
+                        printk("%s: Failed to create ion heap '%s'", __func__, psPlatHeapData->name);
+                        IonDeinit();
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+                }
+
+                ion_device_add_heap(gpsIonDev, gapsIonHeaps[i]);
+        }
+
+        return eError;
+}
+
+void IonDeinit(void)
+{
+        int i;
+        for (i = 0; i < gsTCIonConfig.nr; i++)
+                if (gapsIonHeaps[i])
+                        ion_heap_destroy(gapsIonHeaps[i]);
+        kfree(gapsIonHeaps);
+        ion_device_destroy(gpsIonDev);
+}
+
+#else
+
+#if defined(ION_CARVEOUT_MEM_BASE) && defined(ION_CARVEOUT_MEM_SIZE)
+/* Only define the carveout heap on boards with BASE and SIZE defined,
+ * otherwise crashes may be seen when empty cache flushes are issued
+ * (seen on the MIPS architecture).
+ */
+#define ION_HAS_CARVEOUT_HEAP
+#endif
+
+static struct ion_platform_data gsGenericConfig =
+{
+#if defined(ION_HAS_CARVEOUT_HEAP)
+	.nr = 3,
+#else
+	.nr = 2,
+#endif
+	.heaps =
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,39))
+	(struct ion_platform_heap [])
+#endif
+	{
+		{
+			.type = ION_HEAP_TYPE_SYSTEM,
+			.name = "system",
+			.id   = ION_HEAP_TYPE_SYSTEM,
+		},
+		{
+			.type = ION_HEAP_TYPE_DMA,
+			.name = "dma",
+			.id   = ION_HEAP_TYPE_DMA,
+		},
+#if defined(ION_HAS_CARVEOUT_HEAP)
+		{
+			.type = ION_HEAP_TYPE_CARVEOUT,
+			.name = "carveout",
+			.id   = ION_HEAP_TYPE_CARVEOUT,
+			.base = ION_CARVEOUT_MEM_BASE,
+			.size = ION_CARVEOUT_MEM_SIZE,
+		},
+#endif /* defined(ION_HAS_CARVEOUT_HEAP) */
+	}
+};
+
+PVRSRV_ERROR IonInit(IMG_VOID)
+{
+	int uiHeapCount = gsGenericConfig.nr;
+	int uiError;
+	int i;
+
+	gapsIonHeaps = kzalloc(sizeof(struct ion_heap *) * uiHeapCount, GFP_KERNEL);
+	/* Create the ion devicenode */
+	gpsIonDev = ion_device_create(NULL);
+	if (IS_ERR_OR_NULL(gpsIonDev)) {
+		kfree(gapsIonHeaps);
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Register all the heaps */
+	for (i = 0; i < gsGenericConfig.nr; i++)
+	{
+		struct ion_platform_heap *psPlatHeapData = &gsGenericConfig.heaps[i];
+
+		gapsIonHeaps[i] = ion_heap_create(psPlatHeapData);
+		if (IS_ERR_OR_NULL(gapsIonHeaps[i]))
+		{
+			uiError = PTR_ERR(gapsIonHeaps[i]);
+			goto failHeapCreate;
+		}
+		ion_device_add_heap(gpsIonDev, gapsIonHeaps[i]);
+	}
+
+	return PVRSRV_OK;
+failHeapCreate:
+	for (i = 0; i < uiHeapCount; i++)
+	{
+		if (gapsIonHeaps[i])
+		{
+				ion_heap_destroy(gapsIonHeaps[i]);
+		}
+	}
+	kfree(gapsIonHeaps);
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+IMG_VOID IonDeinit(IMG_VOID)
+{
+	int uiHeapCount = gsGenericConfig.nr;
+	int i;
+
+	for (i = 0; i < uiHeapCount; i++)
+	{
+		if (gapsIonHeaps[i])
+		{
+				ion_heap_destroy(gapsIonHeaps[i]);
+		}
+	}
+	kfree(gapsIonHeaps);
+	ion_device_destroy(gpsIonDev);
+}
+
+#endif /* defined(LMA) */
+
+#endif /* defined(CONFIG_ION_INCDHAD1) */
+
+#endif /* defined(CONFIG_ION_SUNXI) */
+
+#endif /* defined(CONFIG_ION_S5P) */
+
+#endif /* defined(CONFIG_ION_OMAP) */
+
+#define MAX_IMPORT_ION_FDS 3
+
+typedef struct _ION_IMPORT_DATA_
+{
+	/* ion client handles are imported into */
+	struct ion_client *psIonClient;
+
+	/* Number of ion handles represented by this import */
+	IMG_UINT32 ui32NumIonHandles;
+
+	/* Array of ion handles in use by services */
+	struct ion_handle *apsIonHandle[MAX_IMPORT_ION_FDS];
+
+	/* Array of physical addresses represented by these buffers */
+	IMG_SYS_PHYADDR *psSysPhysAddr;
+
+#if defined(PDUMP)
+	/* If ui32NumBuffers is 1 and ion_map_kernel() is implemented by the
+	 * allocator, this may be non-NULL. Otherwise it will be NULL.
+	 */
+	IMG_PVOID pvKernAddr0;
+#endif /* defined(PDUMP) */
+}
+ION_IMPORT_DATA;
+
+PVRSRV_ERROR IonImportBufferAndAcquirePhysAddr(IMG_HANDLE hIonDev,
+											   IMG_UINT32 ui32NumFDs,
+											   IMG_INT32  *pai32BufferFDs,
+											   IMG_UINT32 *pui32PageCount,
+											   IMG_SYS_PHYADDR **ppsSysPhysAddr,
+											   IMG_PVOID  *ppvKernAddr0,
+											   IMG_HANDLE *phPriv,
+											   IMG_HANDLE *phUnique)
+{
+	struct scatterlist *psTemp, *psScatterList[MAX_IMPORT_ION_FDS] = {};
+	PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+	struct ion_client *psIonClient = hIonDev;
+	IMG_UINT32 i, k, ui32PageCount = 0;
+	ION_IMPORT_DATA *psImportData;
+
+	if(ui32NumFDs > MAX_IMPORT_ION_FDS)
+	{
+		printk(KERN_ERR "%s: More ion export fds passed in than supported "
+						"(%d provided, %d max)", __func__, ui32NumFDs,
+						MAX_IMPORT_ION_FDS);
+		return PVRSRV_ERROR_INVALID_PARAMS;
+	}
+
+	psImportData = kzalloc(sizeof(ION_IMPORT_DATA), GFP_KERNEL);
+	if (psImportData == NULL)
+	{
+		goto exitFailKMallocImportData;
+	}
+
+	/* Set up import data for free call */
+	psImportData->psIonClient = psIonClient;
+	psImportData->ui32NumIonHandles = ui32NumFDs;
+
+	for(i = 0; i < ui32NumFDs; i++)
+	{
+		int fd = (int)pai32BufferFDs[i];
+		struct sg_table *psSgTable;
+
+		psImportData->apsIonHandle[i] = ion_import_dma_buf(psIonClient, fd);
+		if (psImportData->apsIonHandle[i] == IMG_NULL)
+		{
+			eError = PVRSRV_ERROR_BAD_MAPPING;
+			goto exitFailImport;
+		}
+
+		psSgTable = ion_sg_table(psIonClient, psImportData->apsIonHandle[i]);
+		psScatterList[i] = psSgTable->sgl;
+		if (psScatterList[i] == NULL)
+		{
+			eError = PVRSRV_ERROR_INVALID_PARAMS;
+			goto exitFailImport;
+		}
+
+		/* Although all heaps will provide an sg_table, the tables cannot
+		 * always be trusted because sg_lists are just pointers to "struct
+		 * page" values, and some memory e.g. carveout may not have valid
+		 * "struct page" values. In particular, on ARM, carveout is
+		 * generally reserved with memblock_remove(), which leaves the
+		 * "struct page" entries uninitialized when SPARSEMEM is enabled.
+		 * The effect of this is that page_to_pfn(pfn_to_page(pfn)) != pfn.
+		 *
+		 * There's more discussion on this mailing list thread:
+		 * http://lists.linaro.org/pipermail/linaro-mm-sig/2012-August/002440.html
+		 *
+		 * If the heap this buffer comes from implements ->phys(), it's
+		 * probably a contiguous allocator. If the phys() function is
+		 * implemented, we'll use it to check sg_table->sgl[0]. If we find
+		 * they don't agree, we'll assume phys() is more reliable and use
+		 * that.
+		 *
+		 * Some heaps out there will implement phys() even though they are
+		 * not for physically contiguous allocations (so the sg_table must
+		 * be used). Therefore use the sg_table if the phys() and first
+		 * sg_table entry match. This should be reliable because for most
+		 * contiguous allocators, the sg_table should be a single span
+		 * from 'start' to 'start+size'.
+		 *
+		 * Also, ion prints out an error message if the heap doesn't implement
+		 * ->phys(), which we want to avoid, so only use ->phys() if the
+		 * sg_table contains a single span and therefore could plausibly
+		 * be a contiguous allocator.
+		 */
+		if(!sg_next(psScatterList[i]))
+		{
+			ion_phys_addr_t sPhyAddr;
+			size_t sLength;
+
+			if(!ion_phys(psIonClient, psImportData->apsIonHandle[i],
+						 &sPhyAddr, &sLength))
+			{
+				BUG_ON(sLength & ~PAGE_MASK);
+
+				if(sg_phys(psScatterList[i]) != sPhyAddr)
+				{
+					psScatterList[i] = IMG_NULL;
+					ui32PageCount += sLength / PAGE_SIZE;
+				}
+			}
+		}
+
+		for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp))
+		{
+			IMG_UINT32 j;
+			for (j = 0; j < psTemp->length; j += PAGE_SIZE)
+			{
+				ui32PageCount++;
+			}
+		}
+	}
+
+	BUG_ON(ui32PageCount == 0);
+
+	psImportData->psSysPhysAddr = kmalloc(sizeof(IMG_SYS_PHYADDR) * ui32PageCount, GFP_KERNEL);
+	if (psImportData->psSysPhysAddr == NULL)
+	{
+		goto exitFailImport;
+	}
+
+	for(i = 0, k = 0; i < ui32NumFDs; i++)
+	{
+		if(psScatterList[i])
+		{
+			for(psTemp = psScatterList[i]; psTemp; psTemp = sg_next(psTemp))
+			{
+				IMG_UINT32 j;
+				for (j = 0; j < psTemp->length; j += PAGE_SIZE)
+				{
+					psImportData->psSysPhysAddr[k].uiAddr = sg_phys(psTemp) + j;
+					k++;
+				}
+			}
+		}
+		else
+		{
+			ion_phys_addr_t sPhyAddr;
+			size_t sLength, j;
+
+			ion_phys(psIonClient, psImportData->apsIonHandle[i],
+					 &sPhyAddr, &sLength);
+
+			for(j = 0; j < sLength; j += PAGE_SIZE)
+			{
+				psImportData->psSysPhysAddr[k].uiAddr = sPhyAddr + j;
+				k++;
+			}
+		}
+	}
+
+	*pui32PageCount = ui32PageCount;
+	*ppsSysPhysAddr = psImportData->psSysPhysAddr;
+
+#if defined(PDUMP)
+	if(ui32NumFDs == 1)
+	{
+		IMG_PVOID pvKernAddr0;
+
+		pvKernAddr0 = ion_map_kernel(psIonClient, psImportData->apsIonHandle[0]);
+		if (IS_ERR(pvKernAddr0))
+		{
+			pvKernAddr0 = IMG_NULL;
+		}
+
+		psImportData->pvKernAddr0 = pvKernAddr0;
+		*ppvKernAddr0 = pvKernAddr0;
+	}
+	else
+#endif /* defined(PDUMP) */
+	{
+		*ppvKernAddr0 = NULL;
+	}
+
+	*phPriv = psImportData;
+	*phUnique = (IMG_HANDLE)psImportData->psSysPhysAddr[0].uiAddr;
+
+	return PVRSRV_OK;
+
+exitFailImport:
+	for(i = 0; psImportData->apsIonHandle[i] != NULL; i++)
+	{
+		ion_free(psIonClient, psImportData->apsIonHandle[i]);
+	}
+	kfree(psImportData);
+exitFailKMallocImportData:
+	return eError;
+}
+
+IMG_VOID IonUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv)
+{
+	ION_IMPORT_DATA *psImportData = hPriv;
+	IMG_UINT32 i;
+
+#if defined(PDUMP)
+	if (psImportData->pvKernAddr0)
+	{
+		ion_unmap_kernel(psImportData->psIonClient, psImportData->apsIonHandle[0]);
+	}
+#endif /* defined(PDUMP) */
+
+	for(i = 0; i < psImportData->ui32NumIonHandles; i++)
+	{
+		ion_free(psImportData->psIonClient, psImportData->apsIonHandle[i]);
+	}
+
+	kfree(psImportData->psSysPhysAddr);
+	kfree(psImportData);
+}
+
+#endif /* defined(SUPPORT_ION) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/ion.h b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.h
new file mode 100644
index 0000000..145ae12
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/ion.h
@@ -0,0 +1,73 @@
+/*************************************************************************/ /*!
+@Title          Ion driver inter-operability code.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __IMG_LINUX_ION_H__
+#define __IMG_LINUX_ION_H__
+
+#if defined(SUPPORT_ION)
+
+#include SUPPORT_ION_HEADER
+
+#include "img_types.h"
+#include "servicesext.h"
+
+#if defined(LMA)
+PVRSRV_ERROR IonInit(void *pvPrivateData);
+#else
+PVRSRV_ERROR IonInit(IMG_VOID);
+#endif
+
+IMG_VOID IonDeinit(IMG_VOID);
+
+PVRSRV_ERROR IonImportBufferAndAcquirePhysAddr(IMG_HANDLE hIonDev,
+											   IMG_UINT32 ui32NumFDs,
+											   IMG_INT32  *pi32BufferFDs,
+											   IMG_UINT32 *pui32PageCount,
+											   IMG_SYS_PHYADDR **ppsSysPhysAddr,
+											   IMG_PVOID *ppvKernAddr0,
+											   IMG_HANDLE *phPriv,
+											   IMG_HANDLE *phUnique);
+
+IMG_VOID IonUnimportBufferAndReleasePhysAddr(IMG_HANDLE hPriv);
+
+#endif /* defined(SUPPORT_ION) */
+
+#endif /* __IMG_LINUX_ION_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h b/drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h
new file mode 100644
index 0000000..3c4b506
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/linkage.h
@@ -0,0 +1,77 @@
+/*************************************************************************/ /*!
+@Title          Linux specific Services code internal interfaces
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Interfaces between various parts of the Linux specific
+                Services code, that don't have any other obvious
+                header file to go into.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
+#if defined(CONFIG_COMPAT)
+long PVRSRV_BridgeCompatDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+
+#endif /* PVR_MANUAL_POWER_CONTROL */
+
+#endif	/* DEBUG */
+
+struct device *PVRLDMGetDevice(void);
+
+#endif /* __LINKAGE_H__ */
+/*****************************************************************************
+ End of file (linkage.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/lma_heap_ion.h b/drivers/gpu/pvr/services4/srvkm/env/linux/lma_heap_ion.h
new file mode 100644
index 0000000..c76effb
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/lma_heap_ion.h
@@ -0,0 +1,45 @@
+/*************************************************************************/ /*!
+@File           lma_heap_ion.h
+@Title          Ion heap for local memory
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include SUPPORT_ION_HEADER
+
+struct ion_heap *lma_heap_create(struct ion_platform_heap *data);
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/lock.h b/drivers/gpu/pvr/services4/srvkm/env/linux/lock.h
new file mode 100644
index 0000000..11adcaa
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/lock.h
@@ -0,0 +1,56 @@
+/*************************************************************************/ /*!
+@Title          Main driver lock
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    The main driver lock, held in most places in
+                the driver.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+/*
+ * Main driver lock, used to ensure driver code is single threaded.
+ * There are some places where this lock must not be taken, such as
+ * in the mmap related deriver entry points.
+ */
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#endif /* __LOCK_H__ */
+/*****************************************************************************
+ End of file (lock.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mm.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.c
new file mode 100644
index 0000000..0e1be1a
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.c
@@ -0,0 +1,2770 @@
+/*************************************************************************/ /*!
+@Title          Misc memory management utility functions for Linux
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#if !defined(PVR_LINUX_MEM_AREA_POOL_MAX_PAGES)
+#define PVR_LINUX_MEM_AREA_POOL_MAX_PAGES 0
+#endif
+
+#include <linux/kernel.h>
+#include <asm/atomic.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0))
+#include <linux/shrinker.h>
+#endif
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "syscommon.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	#include "lists.h"
+#endif
+
+/* Decide whether or not DevMem allocs need __GFP_DMA32 */
+#ifndef SGX_FEATURE_36BIT_MMU
+	#if defined CONFIG_X86_PAE || defined CONFIG_ARM_LPAE || defined CONFIG_XPA || defined CONFIG_64BIT
+		#define PVR_USE_DMA32_FOR_DEVMEM_ALLOCS
+	#endif
+#endif
+
+/*
+ * The page pool entry count is an atomic int so that the shrinker function
+ * can return it even when we can't take the lock that protects the page pool
+ * list.
+ */
+static atomic_t g_sPagePoolEntryCount = ATOMIC_INIT(0);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+typedef enum {
+    DEBUG_MEM_ALLOC_TYPE_KMALLOC = 0,
+    DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+    DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+    DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+    DEBUG_MEM_ALLOC_TYPE_IO,
+    DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+    DEBUG_MEM_ALLOC_TYPE_ION,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    DEBUG_MEM_ALLOC_TYPE_VMAP,
+#endif
+    DEBUG_MEM_ALLOC_TYPE_SWAP,
+    DEBUG_MEM_ALLOC_TYPE_COUNT
+} DEBUG_MEM_ALLOC_TYPE;
+
+typedef struct _DEBUG_MEM_ALLOC_REC
+{
+    DEBUG_MEM_ALLOC_TYPE    eAllocType;
+	IMG_UINTPTR_T			uiKey; /* Some unique value (private to the eAllocType) */
+    IMG_VOID                *pvCpuVAddr;
+    IMG_CPU_PHYADDR         sCpuPAddr;
+    IMG_VOID                *pvPrivateData;
+	IMG_SIZE_T				uiBytes;
+	pid_t					pid;
+    IMG_CHAR                *pszFileName;
+    IMG_UINT32              ui32Line;
+    
+    struct _DEBUG_MEM_ALLOC_REC   *psNext;
+	struct _DEBUG_MEM_ALLOC_REC   **ppsThis;
+} DEBUG_MEM_ALLOC_REC;
+
+static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC)
+
+
+static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
+static DEBUG_MEM_ALLOC_REC *g_SwapMemoryRecords;
+
+static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+
+/* vmalloc + kmalloc + alloc_pages + kmem_cache */
+static IMG_UINT32 g_SysRAMWaterMark;		/* Doesn't include page pool */
+static IMG_UINT32 g_SysRAMHighWaterMark;	/* *DOES* include page pool */
+
+static inline IMG_UINT32
+SysRAMTrueWaterMark(void)
+{
+	return g_SysRAMWaterMark + PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount)) + g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_SWAP];
+}
+
+/* ioremap + io */
+static IMG_UINT32 g_IOMemWaterMark;
+static IMG_UINT32 g_IOMemHighWaterMark;
+
+static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+                                       IMG_UINTPTR_T uiKey,
+                                       IMG_VOID *pvCpuVAddr,
+                                       IMG_CPU_PHYADDR sCpuPAddr,
+                                       IMG_VOID *pvPrivateData,
+                                       IMG_SIZE_T uiBytes,
+                                       IMG_CHAR *pszFileName,
+                                       IMG_UINT32 ui32Line);
+
+static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_UINTPTR_T uiKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
+
+
+static struct pvr_proc_dir_entry *g_SeqFileMemoryRecords;
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+typedef struct _DEBUG_LINUX_MEM_AREA_REC
+{
+	LinuxMemArea                *psLinuxMemArea;
+    IMG_UINT32                  ui32Flags;
+	pid_t					    pid;
+
+	struct _DEBUG_LINUX_MEM_AREA_REC  *psNext;
+	struct _DEBUG_LINUX_MEM_AREA_REC  **ppsThis;
+}DEBUG_LINUX_MEM_AREA_REC;
+
+
+static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC)
+
+
+
+
+static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
+static IMG_UINT32 g_LinuxMemAreaCount;
+static IMG_UINT32 g_LinuxMemAreaWaterMark;
+static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
+
+
+static struct pvr_proc_dir_entry *g_SeqFileMemArea;
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static PVRSRV_LINUX_MUTEX g_sDebugMutex;
+static PVRSRV_LINUX_MUTEX g_sSwapDebugMutex;
+#endif
+
+#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
+#endif
+
+typedef	struct
+{
+	/* Linkage for page pool LRU list */
+	struct list_head sPagePoolItem;
+
+	struct page *psPage;
+} LinuxPagePoolEntry;
+
+static LinuxKMemCache *g_PsLinuxMemAreaCache;
+static LinuxKMemCache *g_PsLinuxPagePoolCache;
+
+static LIST_HEAD(g_sPagePoolList);
+static int g_iPagePoolMaxEntries;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_SIZE_T uiLength);
+static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_SIZE_T uiLength);
+#endif
+
+static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
+static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea);
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags);
+static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea);
+static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
+#endif
+
+
+static inline IMG_BOOL
+AreaIsUncached(IMG_UINT32 ui32AreaFlags)
+{
+	return (ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED)) != 0;
+}
+
+static inline IMG_BOOL
+CanFreeToPool(LinuxMemArea *psLinuxMemArea)
+{
+	return AreaIsUncached(psLinuxMemArea->ui32AreaFlags) && !psLinuxMemArea->bNeedsCacheInvalidate;
+}
+
+IMG_VOID *
+_KMallocWrapper(IMG_SIZE_T uiByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line, IMG_BOOL bSwapAlloc)
+{
+    IMG_VOID *pvRet;
+    pvRet = kmalloc(uiByteSize, uFlags);
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if (pvRet)
+    {
+		IMG_CPU_PHYADDR sCpuPAddr;
+		sCpuPAddr.uiAddr = 0;
+
+        DebugMemAllocRecordAdd(bSwapAlloc ? DEBUG_MEM_ALLOC_TYPE_SWAP : DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+                               (IMG_UINTPTR_T)pvRet,
+                               pvRet,
+                               sCpuPAddr,
+                               NULL,
+                               uiByteSize,
+                               pszFileName,
+                               ui32Line
+                              );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+    PVR_UNREFERENCED_PARAMETER(bSwapAlloc);
+#endif
+    return pvRet;
+}
+
+void
+_KFreeWrapper(void *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line, IMG_BOOL bSwapAlloc)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(
+			bSwapAlloc ? DEBUG_MEM_ALLOC_TYPE_SWAP : DEBUG_MEM_ALLOC_TYPE_KMALLOC, 
+			(IMG_UINTPTR_T)pvCpuVAddr, 
+			pszFileName,  
+			ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+    PVR_UNREFERENCED_PARAMETER(bSwapAlloc);
+#endif
+    kfree(pvCpuVAddr);
+}
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID
+DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+                       IMG_UINTPTR_T uiKey,
+                       IMG_VOID *pvCpuVAddr,
+                       IMG_CPU_PHYADDR sCpuPAddr,
+                       IMG_VOID *pvPrivateData,
+                       IMG_SIZE_T uiBytes,
+                       IMG_CHAR *pszFileName,
+                       IMG_UINT32 ui32Line)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+
+    psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
+
+    psRecord->eAllocType = eAllocType;
+    psRecord->uiKey = uiKey;
+    psRecord->pvCpuVAddr = pvCpuVAddr;
+    psRecord->sCpuPAddr.uiAddr = sCpuPAddr.uiAddr;
+    psRecord->pvPrivateData = pvPrivateData;
+    psRecord->pid = OSGetCurrentProcessIDKM();
+    psRecord->uiBytes = uiBytes;
+    psRecord->pszFileName = pszFileName;
+    psRecord->ui32Line = ui32Line;
+  
+    if (eAllocType == DEBUG_MEM_ALLOC_TYPE_SWAP)
+    {
+    	LinuxLockMutexNested(&g_sSwapDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
+
+	List_DEBUG_MEM_ALLOC_REC_Insert(&g_SwapMemoryRecords, psRecord);
+
+	g_WaterMarkData[eAllocType] += uiBytes;
+	if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+    	{   
+            g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+    	}
+
+    	LinuxUnLockMutex(&g_sSwapDebugMutex);
+	return;
+    }
+    
+    LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
+    List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
+    
+    g_WaterMarkData[eAllocType] += uiBytes;
+    if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+    {
+        g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+    }
+
+    if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+       || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+    {
+		IMG_SIZE_T uSysRAMTrueWaterMark;
+
+        g_SysRAMWaterMark += uiBytes;
+		uSysRAMTrueWaterMark = SysRAMTrueWaterMark();
+
+        if (uSysRAMTrueWaterMark > g_SysRAMHighWaterMark)
+        {
+            g_SysRAMHighWaterMark = uSysRAMTrueWaterMark;
+        }
+    }
+    else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+            || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+    {
+        g_IOMemWaterMark += uiBytes;
+        if (g_IOMemWaterMark > g_IOMemHighWaterMark)
+        {
+            g_IOMemHighWaterMark = g_IOMemWaterMark;
+        }
+    }
+
+    LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
+{
+	DEBUG_MEM_ALLOC_TYPE eAllocType;
+	IMG_UINTPTR_T uiKey;
+	
+	eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
+	uiKey = va_arg(va, IMG_UINTPTR_T);
+
+	if (psCurrentRecord->eAllocType == eAllocType
+		&& psCurrentRecord->uiKey == uiKey)
+	{
+		g_WaterMarkData[eAllocType] -= psCurrentRecord->uiBytes;
+		
+		if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+		   || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+		   || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+		   || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+		{
+			g_SysRAMWaterMark -= psCurrentRecord->uiBytes;
+		}
+		else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+				|| eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+		{
+			g_IOMemWaterMark -= psCurrentRecord->uiBytes;
+		}
+		
+		List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
+		kfree(psCurrentRecord);
+
+		return IMG_TRUE;
+	}
+	else
+	{
+		return IMG_FALSE;
+	}
+}
+
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_UINTPTR_T uiKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+/*    DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;*/
+
+    LinuxLockMutexNested(eAllocType ==  DEBUG_MEM_ALLOC_TYPE_SWAP ? &g_sSwapDebugMutex : &g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
+
+    /* Locate the corresponding allocation entry */
+	if (!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(eAllocType ==  DEBUG_MEM_ALLOC_TYPE_SWAP ? g_SwapMemoryRecords : g_MemoryRecords,
+												DebugMemAllocRecordRemove_AnyVaCb,
+												eAllocType,
+												uiKey))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with uiKey=" UINTPTR_FMT " (called from %s, line %d\n",
+		__FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), uiKey,
+		pszFileName, ui32Line));
+	}
+
+    LinuxUnLockMutex(eAllocType ==  DEBUG_MEM_ALLOC_TYPE_SWAP ? &g_sSwapDebugMutex : &g_sDebugMutex);
+}
+
+
+static IMG_CHAR *
+DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+    IMG_CHAR *apszDebugMemoryRecordTypes[] = {
+        "KMALLOC",
+        "VMALLOC",
+        "ALLOC_PAGES",
+        "IOREMAP",
+        "IO",
+        "KMEM_CACHE_ALLOC",
+		"ION",
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+		"VMAP",
+#endif
+	"SWAPALLOC",
+    };
+    return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+
+static IMG_BOOL
+AllocFlagsToPGProt(pgprot_t *pPGProtFlags, IMG_UINT32 ui32AllocFlags)
+{
+    pgprot_t PGProtFlags;
+
+    switch (ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+            PGProtFlags = PAGE_KERNEL;
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+            PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR,
+                     "%s: Unknown mapping flags=0x%08x",
+                     __FUNCTION__, ui32AllocFlags));
+            dump_stack();
+            return IMG_FALSE;
+    }
+
+    *pPGProtFlags = PGProtFlags;
+
+    return IMG_TRUE;
+}
+
+IMG_VOID *
+_VMallocWrapper(IMG_SIZE_T uiBytes,
+                IMG_UINT32 ui32AllocFlags,
+                IMG_CHAR *pszFileName,
+                IMG_UINT32 ui32Line)
+{
+    pgprot_t PGProtFlags;
+    IMG_VOID *pvRet;
+	gfp_t gfp_mask; 
+    
+    if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+    {
+            return NULL;
+    }
+
+	gfp_mask = GFP_KERNEL;
+
+#if defined(PVR_USE_DMA32_FOR_DEVMEM_ALLOCS)
+#ifdef CONFIG_ZONE_DMA32
+	gfp_mask |= __GFP_DMA32;
+#else
+	gfp_mask |= __GFP_DMA;
+#endif
+#else
+	gfp_mask |= __GFP_HIGHMEM;
+#endif
+
+	/* Allocate virtually contiguous pages */
+    pvRet = __vmalloc(uiBytes, gfp_mask, PGProtFlags);
+    
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if (pvRet)
+    {
+		IMG_CPU_PHYADDR sCpuPAddr;
+		sCpuPAddr.uiAddr = 0;
+
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+                               (IMG_UINTPTR_T)pvRet,
+                               pvRet,
+                               sCpuPAddr,
+                               NULL,
+                               PAGE_ALIGN(uiBytes),
+                               pszFileName,
+                               ui32Line
+                              );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvRet;
+}
+
+
+IMG_VOID
+_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(
+			DEBUG_MEM_ALLOC_TYPE_VMALLOC, 
+			(IMG_UINTPTR_T)pvCpuVAddr, 
+			pszFileName, 
+			ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    vfree(pvCpuVAddr);
+}
+
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+static IMG_VOID *
+_VMapWrapper(struct page **ppsPageList, IMG_UINT32 ui32NumPages, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+    pgprot_t PGProtFlags;
+    IMG_VOID *pvRet;
+
+    if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+    {
+            return NULL;
+    }
+
+    pvRet = vmap(ppsPageList, ui32NumPages, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if (pvRet)
+    {
+		IMG_CPU_PHYADDR sCpuPAddr;
+		sCpuPAddr.uiAddr = 0;
+
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMAP,
+                               (IMG_UINTPTR_T)pvRet,
+                               pvRet,
+                               sCpuPAddr,
+                               NULL,
+                               PAGES_TO_BYTES(ui32NumPages),
+                               pszFileName,
+                               ui32Line
+                              );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvRet;
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMapWrapper(ppsPageList, uBytes, ui32AllocFlags) _VMapWrapper(ppsPageList, uBytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMapWrapper(ppsPageList, uBytes, ui32AllocFlags) _VMapWrapper(ppsPageList, uBytes, ui32AllocFlags, NULL, 0)
+#endif
+
+
+static IMG_VOID
+_VUnmapWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMAP,
+							  (IMG_UINTPTR_T)pvCpuVAddr, pszFileName, ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    vunmap(pvCpuVAddr);
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, NULL, 0)
+#endif
+
+#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(
+			DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, 
+			(IMG_UINTPTR_T)pvObject, 
+			pszFileName, 
+			ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+    PVR_UNREFERENCED_PARAMETER(psCache);
+
+    /* In this case kmem_cache_t is an incomplete typedef,
+     * so we can't even de-reference to get the name member. It is also a GPL export symbol */
+    return "";
+}
+
+
+static LinuxPagePoolEntry *
+LinuxPagePoolEntryAlloc(IMG_VOID)
+{
+    return KMemCacheAllocWrapper(g_PsLinuxPagePoolCache, GFP_KERNEL);
+}
+
+static IMG_VOID
+LinuxPagePoolEntryFree(LinuxPagePoolEntry *psPagePoolEntry)
+{
+	KMemCacheFreeWrapper(g_PsLinuxPagePoolCache, psPagePoolEntry);
+}
+
+
+static struct page *
+AllocPageFromLinux(void)
+{
+	struct page *psPage;
+	gfp_t gfp_mask; 
+
+	gfp_mask = GFP_KERNEL;
+
+#if defined(PVR_USE_DMA32_FOR_DEVMEM_ALLOCS)
+#ifdef CONFIG_ZONE_DMA32
+	gfp_mask |= __GFP_DMA32;
+#else
+	gfp_mask |= __GFP_DMA;
+#endif
+#else
+	gfp_mask |= __GFP_HIGHMEM;
+#endif
+
+	/* PF_DUMPCORE is treated by the VM as if the OOM killer was disabled */
+	WARN_ON(current->flags & PF_DUMPCORE);
+	current->flags |= PF_DUMPCORE;
+
+	psPage = alloc_pages(gfp_mask, 0);
+	current->flags &= ~PF_DUMPCORE;
+	if (!psPage)
+	{
+		return NULL;
+
+	}
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+    	/* Reserve those pages to allow them to be re-mapped to user space */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))		
+    	SetPageReserved(psPage);
+#else
+        mem_map_reserve(psPage);
+#endif
+#endif
+	return psPage;
+}
+
+
+static IMG_VOID
+FreePageToLinux(struct page *psPage)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))		
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))		
+        ClearPageReserved(psPage);
+#else
+        mem_map_reserve(psPage);
+#endif		
+#endif	
+        __free_pages(psPage, 0);
+}
+
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+static DEFINE_MUTEX(g_sPagePoolMutex);
+
+static inline void
+PagePoolLock(void)
+{
+	mutex_lock(&g_sPagePoolMutex);
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+	mutex_unlock(&g_sPagePoolMutex);
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+	return mutex_trylock(&g_sPagePoolMutex);
+}
+
+#else	/* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */
+static inline void
+PagePoolLock(void)
+{
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+	return 1;
+}
+#endif	/* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */
+
+
+static inline void
+AddEntryToPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+	list_add_tail(&psPagePoolEntry->sPagePoolItem, &g_sPagePoolList);
+	atomic_inc(&g_sPagePoolEntryCount);
+}
+
+static inline void
+RemoveEntryFromPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+	list_del(&psPagePoolEntry->sPagePoolItem);
+	atomic_dec(&g_sPagePoolEntryCount);
+}
+
+static inline LinuxPagePoolEntry *
+RemoveFirstEntryFromPool(void)
+{
+	LinuxPagePoolEntry *psPagePoolEntry;
+
+	if (list_empty(&g_sPagePoolList))
+	{
+		PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+		return NULL;
+	}
+
+	PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) > 0);
+
+	psPagePoolEntry = list_first_entry(&g_sPagePoolList, LinuxPagePoolEntry, sPagePoolItem);
+
+	RemoveEntryFromPool(psPagePoolEntry);
+
+	return psPagePoolEntry;
+}
+
+static struct page *
+AllocPage(IMG_UINT32 ui32AreaFlags, IMG_BOOL *pbFromPagePool)
+{
+	struct page *psPage = NULL;
+
+	/*
+	 * Only uncached allocations can come from the page pool.
+	 * The page pool is currently used to reduce the cost of
+	 * invalidating the CPU cache when uncached memory is allocated.
+	 */
+	if (AreaIsUncached(ui32AreaFlags) && atomic_read(&g_sPagePoolEntryCount) != 0)
+	{
+		LinuxPagePoolEntry *psPagePoolEntry;
+
+		PagePoolLock();
+		psPagePoolEntry = RemoveFirstEntryFromPool();
+		PagePoolUnlock();
+
+		/* List may have changed since we checked the counter */
+		if (psPagePoolEntry)
+		{
+			psPage = psPagePoolEntry->psPage;
+			LinuxPagePoolEntryFree(psPagePoolEntry);
+			*pbFromPagePool = IMG_TRUE;
+		}
+	}
+
+	if (!psPage)
+	{
+		psPage = AllocPageFromLinux();
+		if (psPage)
+		{
+			*pbFromPagePool = IMG_FALSE;
+		}
+	}
+
+	return psPage;
+
+}
+
+static IMG_VOID
+FreePage(IMG_BOOL bToPagePool, struct page *psPage)
+{
+	/* Only uncached allocations can be freed to the page pool */
+	if (bToPagePool && atomic_read(&g_sPagePoolEntryCount) < g_iPagePoolMaxEntries)
+	{
+		LinuxPagePoolEntry *psPagePoolEntry = LinuxPagePoolEntryAlloc();
+		if (psPagePoolEntry)
+		{
+			psPagePoolEntry->psPage = psPage;
+
+			PagePoolLock();
+			AddEntryToPool(psPagePoolEntry);
+			PagePoolUnlock();
+
+			return;
+		}
+	}
+
+	FreePageToLinux(psPage);
+}
+
+static IMG_VOID
+FreePagePool(IMG_VOID)
+{
+	LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+
+	PagePoolLock();
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+	PVR_TRACE(("%s: Freeing %d pages from pool", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+#else
+	PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+	PVR_ASSERT(list_empty(&g_sPagePoolList));
+#endif
+
+	list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+	{
+		RemoveEntryFromPool(psPagePoolEntry);
+
+		FreePageToLinux(psPagePoolEntry->psPage);
+		LinuxPagePoolEntryFree(psPagePoolEntry);
+	}
+
+	PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+	PagePoolUnlock();
+}
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+static struct shrinker g_sShrinker;
+#endif
+
+static unsigned long
+CountObjectsInPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+	PVR_ASSERT(psShrinker == &g_sShrinker);
+	(void)psShrinker;
+	(void)psShrinkControl;
+
+	return atomic_read(&g_sPagePoolEntryCount);
+}
+
+static unsigned long
+ScanObjectsInPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+	unsigned long uNumToScan = psShrinkControl->nr_to_scan;
+	LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+
+	PVR_ASSERT(psShrinker == &g_sShrinker);
+	(void)psShrinker;
+
+	PVR_TRACE(("%s: Number to scan: %ld", __FUNCTION__, uNumToScan));
+	PVR_TRACE(("%s: Pages in pool before scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+
+	if (!PagePoolTrylock())
+	{
+		PVR_TRACE(("%s: Couldn't get page pool lock", __FUNCTION__));
+		return -1;
+	}
+
+	list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+	{
+		RemoveEntryFromPool(psPagePoolEntry);
+
+		FreePageToLinux(psPagePoolEntry->psPage);
+		LinuxPagePoolEntryFree(psPagePoolEntry);
+
+		if (--uNumToScan == 0)
+		{
+			break;
+		}
+	}
+
+	if (list_empty(&g_sPagePoolList))
+	{
+		PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+	}
+
+	PagePoolUnlock();
+
+	PVR_TRACE(("%s: Pages in pool after scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+
+	return atomic_read(&g_sPagePoolEntryCount);
+}
+#endif /* defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK) */
+
+static IMG_BOOL
+AllocPages(IMG_UINT32 ui32AreaFlags, struct page ***pppsPageList, IMG_HANDLE *phBlockPageList, IMG_UINT32 ui32NumPages, IMG_BOOL *pbFromPagePool)
+{
+    struct page **ppsPageList;
+    IMG_HANDLE hBlockPageList;
+    IMG_INT32 i;		/* Must be signed; see "for" loop conditions */
+    PVRSRV_ERROR eError;
+    IMG_BOOL bFromPagePool = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+
+    eError = OSAllocMem(0, sizeof(*ppsPageList) * ui32NumPages, (IMG_VOID **)&ppsPageList, &hBlockPageList,
+							"Array of pages");
+    if (eError != PVRSRV_OK)
+    {
+        goto failed_page_list_alloc;
+    }
+    
+    *pbFromPagePool = IMG_TRUE;
+    for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
+    {
+        ppsPageList[i] = AllocPage(ui32AreaFlags, &bFromPagePool);
+        if (!ppsPageList[i])
+        {
+            goto failed_alloc_pages;
+        }
+	*pbFromPagePool &= bFromPagePool;
+    }
+
+    *pppsPageList = ppsPageList;
+    *phBlockPageList = hBlockPageList;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	sCpuPAddr.uiAddr = 0;
+
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+                           (IMG_UINTPTR_T)ppsPageList,
+                           0,
+                           sCpuPAddr,
+                           NULL,
+                           PAGES_TO_BYTES(ui32NumPages),
+                           "unknown",
+                           0
+                          );
+#endif
+
+    return IMG_TRUE;
+    
+failed_alloc_pages:
+    for(i--; i >= 0; i--)
+    {
+        FreePage(*pbFromPagePool, ppsPageList[i]);
+    }
+    (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
+
+failed_page_list_alloc:
+    return IMG_FALSE;
+}
+
+
+static IMG_VOID
+FreePages(IMG_BOOL bToPagePool, struct page **ppsPageList, IMG_HANDLE hBlockPageList, IMG_UINT32 ui32NumPages)
+{
+    IMG_INT32 i;
+
+    for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
+    {
+        FreePage(bToPagePool, ppsPageList[i]);
+    }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(
+			DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, 
+			(IMG_UINTPTR_T)ppsPageList, 
+			__FILE__, 
+			__LINE__);
+#endif
+
+    (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
+}
+
+
+LinuxMemArea *
+NewVMallocLinuxMemArea(IMG_SIZE_T uBytes, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea = NULL;
+    IMG_VOID *pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    IMG_UINT32 ui32NumPages = 0;
+    struct page **ppsPageList = NULL;
+    IMG_HANDLE hBlockPageList;
+#endif
+    IMG_BOOL bFromPagePool = IMG_FALSE;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if (!psLinuxMemArea)
+    {
+        goto failed;
+    }
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    ui32NumPages = RANGE_TO_PAGES(uBytes);
+
+    if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
+    {
+	goto failed;
+    }
+
+    pvCpuVAddr = VMapWrapper(ppsPageList, ui32NumPages, ui32AreaFlags);
+#else	/* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
+    pvCpuVAddr = VMallocWrapper(uBytes, ui32AreaFlags);
+    if (!pvCpuVAddr)
+    {
+        goto failed;
+    }
+/* PG_reserved was deprecated in linux-2.6.15 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+    /* Reserve those pages to allow them to be re-mapped to user space */
+    ReservePages(pvCpuVAddr, uBytes);
+#endif
+#endif	/* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */ 
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
+    psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    psLinuxMemArea->uData.sVmalloc.ppsPageList = ppsPageList;
+    psLinuxMemArea->uData.sVmalloc.hBlockPageList = hBlockPageList;
+#endif
+    psLinuxMemArea->uiByteSize = uBytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    /* This works around a problem where Linux will not invalidate
+     * the cache for physical memory it frees that is direct mapped.
+     *
+     * As a result, cache entries remain that may be subsequently flushed
+     * to these physical pages after they have been allocated for another
+     * purpose. For a subsequent cached use of this memory, that is not a
+     * problem, but if we are allocating uncached or write-combined memory,
+     * and bypassing the cache, it can cause subsequent uncached writes to
+     * the memory to be replaced with junk from the cache.
+     *
+     * If the pages are from our page cache, no cache invalidate is needed.
+     *
+     * This just handles the __vmalloc() case (when we have a kernel virtual
+     * address range). The alloc_pages() path is handled in mmap.c.
+     */
+    if (AreaIsUncached(ui32AreaFlags) && !bFromPagePool)
+    {
+        OSInvalidateCPUCacheRangeKM(psLinuxMemArea, 0, pvCpuVAddr, uBytes);
+    }
+
+    return psLinuxMemArea;
+
+failed:
+    PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    if (ppsPageList)
+    {
+	FreePages(bFromPagePool, ppsPageList, hBlockPageList, ui32NumPages);
+    }
+#endif
+    if (psLinuxMemArea)
+    {
+        LinuxMemAreaStructFree(psLinuxMemArea);
+    }
+
+    return NULL;
+}
+
+
+IMG_VOID
+FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    IMG_UINT32 ui32NumPages;
+    struct page **ppsPageList;
+    IMG_HANDLE hBlockPageList;
+#endif
+
+    PVR_ASSERT(psLinuxMemArea);
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
+    PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+    PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+             __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    VUnmapWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+    ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->uiByteSize);
+    ppsPageList = psLinuxMemArea->uData.sVmalloc.ppsPageList;
+    hBlockPageList = psLinuxMemArea->uData.sVmalloc.hBlockPageList;
+    
+    FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+#else
+/* PG_reserved was deprecated in linux-2.6.15 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+    UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+                    psLinuxMemArea->uiByteSize);
+#endif
+
+    VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+#endif	/* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */ 
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+/* Reserve pages of memory in order that they're not automatically
+   deallocated after the last user reference dies. */
+static IMG_VOID
+ReservePages(IMG_VOID *pvAddress, IMG_SIZE_T uLength)
+{
+	IMG_VOID *pvPage;
+	IMG_VOID *pvEnd = pvAddress + uLength;
+
+	for(pvPage = pvAddress; pvPage < pvEnd;  pvPage += PAGE_SIZE)
+	{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+		SetPageReserved(vmalloc_to_page(pvPage));
+#else
+		mem_map_reserve(vmalloc_to_page(pvPage));
+#endif
+	}
+}
+
+
+/* Un-reserve pages of memory in order that they can be freed. */
+static IMG_VOID
+UnreservePages(IMG_VOID *pvAddress, IMG_SIZE_T uLength)
+{
+	IMG_VOID *pvPage;
+	IMG_VOID *pvEnd = pvAddress + uLength;
+
+	for(pvPage = pvAddress; pvPage < pvEnd;  pvPage += PAGE_SIZE)
+	{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+		ClearPageReserved(vmalloc_to_page(pvPage));
+#else
+		mem_map_unreserve(vmalloc_to_page(pvPage));
+#endif
+	}
+}
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */
+
+
+IMG_VOID *
+_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+               IMG_SIZE_T uBytes,
+               IMG_UINT32 ui32MappingFlags,
+               IMG_CHAR *pszFileName,
+               IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvIORemapCookie;
+    
+    switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+	    pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, uBytes);
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+	    pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, uBytes);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, uBytes);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
+            return NULL;
+    }
+    
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    if (pvIORemapCookie)
+    {
+        DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+                               (IMG_UINTPTR_T)pvIORemapCookie,
+                               pvIORemapCookie,
+                               BasePAddr,
+                               NULL,
+                               uBytes,
+                               pszFileName,
+                               ui32Line
+                              );
+    }
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+    return pvIORemapCookie;
+}
+
+
+IMG_VOID
+_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(
+			DEBUG_MEM_ALLOC_TYPE_IOREMAP, 
+			(IMG_UINTPTR_T)pvIORemapCookie, 
+			pszFileName, 
+			ui32Line);
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    iounmap(pvIORemapCookie);
+}
+
+
+LinuxMemArea *
+NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+                       IMG_SIZE_T uBytes,
+                       IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_VOID *pvIORemapCookie;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if (!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    pvIORemapCookie = IORemapWrapper(BasePAddr, uBytes, ui32AreaFlags);
+    if (!pvIORemapCookie)
+    {
+        LinuxMemAreaStructFree(psLinuxMemArea);
+        return NULL;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
+    psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
+    psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
+    psLinuxMemArea->uiByteSize = uBytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Avoid using remap_pfn_range on RAM, if possible.  On x86 systems, with
+ * PAT enabled, remap_pfn_range checks the page attributes requested by 
+ * remap_pfn_range against those of the direct kernel mapping for those
+ * pages (if any).  This is rather annoying if the pages have been obtained
+ * with alloc_pages, where we just ask for raw pages; we don't care about
+ * the direct mapping.  This latter issue arises when device memory is
+ * exported from one process to another.  Services implements this
+ * using memory wrapping, which ends up creating an external KV memory area.
+ */
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_SIZE_T uBytes, IMG_BOOL bPhysContig)
+{
+	IMG_UINT32 ui32;
+	IMG_UINT32 ui32AddrChk;
+	IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(uBytes);
+
+	/*
+	 * If bPhysContig is IMG_TRUE, we must assume psSysPhysAddr points
+	 * to the address of the first page, not an array of page addresses.
+	 */
+	for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+		ui32 < ui32NumPages;
+		ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+	{
+		if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+		{
+			break;
+		}
+	}
+	if (ui32 == ui32NumPages)
+	{
+		return IMG_FALSE;
+	}
+
+	if (!bPhysContig)
+	{
+		for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+			ui32 < ui32NumPages;
+			ui32++, ui32AddrChk += PAGE_SIZE)
+		{
+			if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+			{
+				return IMG_FALSE;
+			}
+		}
+	}
+
+	return IMG_TRUE;
+}
+#endif
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_SIZE_T uBytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if (!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+    psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+    psLinuxMemArea->uData.sExternalKV.bPhysContig =
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+	(bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, uBytes, bPhysContig))
+                                                    ? IMG_TRUE : IMG_FALSE;
+#else
+	bPhysContig;
+#endif
+    if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+    {
+	psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+    }
+    else
+    {
+	psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+    }
+    psLinuxMemArea->uiByteSize = uBytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+                  IMG_SIZE_T uBytes,
+                  IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if (!psLinuxMemArea)
+    {
+        return NULL;
+    }
+
+    /* Nothing to activly do. We just keep a record of the physical range. */
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
+    psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
+    psLinuxMemArea->uiByteSize = uBytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
+                           BasePAddr.uiAddr,
+                           0,
+                           BasePAddr,
+                           NULL,
+                           uBytes,
+                           "unknown",
+                           0
+                          );
+#endif
+   
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
+    
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
+                              psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr,
+							  __FILE__, 
+							  __LINE__);
+#endif
+
+    /* Nothing more to do than free the LinuxMemArea struct */
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewAllocPagesLinuxMemArea(IMG_SIZE_T uBytes, IMG_UINT32 ui32AreaFlags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    IMG_UINT32 ui32NumPages;
+    struct page **ppsPageList;
+    IMG_HANDLE hBlockPageList;
+    IMG_BOOL bFromPagePool;
+
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if (!psLinuxMemArea)
+    {
+        goto failed_area_alloc;
+    }
+    
+    ui32NumPages = RANGE_TO_PAGES(uBytes);
+
+    if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
+    {
+	goto failed_alloc_pages;
+    }
+
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+    psLinuxMemArea->uData.sPageList.ppsPageList = ppsPageList;
+    psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+    psLinuxMemArea->uiByteSize = uBytes;
+    psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+    /* We defer the cache flush to the first user mapping of this memory */
+    psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags) && !bFromPagePool;
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+    return psLinuxMemArea;
+    
+failed_alloc_pages:
+    LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+    PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
+    
+    return NULL;
+}
+
+
+IMG_VOID
+FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    IMG_UINT32 ui32NumPages;
+    struct page **ppsPageList;
+    IMG_HANDLE hBlockPageList;
+
+    PVR_ASSERT(psLinuxMemArea);
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->uiByteSize);
+    ppsPageList = psLinuxMemArea->uData.sPageList.ppsPageList;
+    hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
+    
+    FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+  
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+struct page*
+LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
+                         IMG_UINTPTR_T uByteOffset)
+{
+    IMG_UINTPTR_T uPageIndex;
+    IMG_CHAR *pui8Addr;
+
+    switch (psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            uPageIndex = PHYS_TO_PFN(uByteOffset);
+            return psLinuxMemArea->uData.sPageList.ppsPageList[uPageIndex];
+ 
+        case LINUX_MEM_AREA_VMALLOC:
+            pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+            pui8Addr += uByteOffset;
+            return vmalloc_to_page(pui8Addr);
+ 
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            /* PRQA S 3670 3 */ /* ignore recursive warning */
+            return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+                                            psLinuxMemArea->uData.sSubAlloc.uiByteOffset
+                                             + uByteOffset);
+        default:
+            PVR_DPF((PVR_DBG_ERROR,
+                    "%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+                    __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+            return NULL;
+    }
+}
+
+
+LinuxKMemCache *
+KMemCacheCreateWrapper(IMG_CHAR *pszName,
+                       size_t Size,
+                       size_t Align,
+                       IMG_UINT32 ui32Flags)
+{
+#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
+    ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
+#endif
+    return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+				, NULL
+#endif	/* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) */
+			   );
+}
+
+
+IMG_VOID
+KMemCacheDestroyWrapper(LinuxKMemCache *psCache)
+{
+    kmem_cache_destroy(psCache);
+}
+
+
+IMG_VOID *
+_KMemCacheAllocWrapper(LinuxKMemCache *psCache,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+                      gfp_t Flags,
+#else
+                      IMG_INT Flags,
+#endif
+                      IMG_CHAR *pszFileName,
+                      IMG_UINT32 ui32Line)
+{
+    IMG_VOID *pvRet;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+   	IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+
+    pvRet = kmem_cache_zalloc(psCache, Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	sCpuPAddr.uiAddr = 0;
+    DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+                           (IMG_UINTPTR_T)pvRet,
+                           pvRet,
+                           sCpuPAddr,
+                           psCache,
+                           kmem_cache_size(psCache),
+                           pszFileName,
+                           ui32Line
+                          );
+#else
+    PVR_UNREFERENCED_PARAMETER(pszFileName);
+    PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+    
+    return pvRet;
+}
+
+
+LinuxMemArea *
+NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+                   IMG_UINTPTR_T uiByteOffset,
+                   IMG_SIZE_T uBytes)
+{
+    LinuxMemArea *psLinuxMemArea;
+    
+    PVR_ASSERT((uiByteOffset + uBytes) <= psParentLinuxMemArea->uiByteSize);
+    
+    psLinuxMemArea = LinuxMemAreaStructAlloc();
+    if (!psLinuxMemArea)
+    {
+        return NULL;
+    }
+    
+    psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+    psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
+    psLinuxMemArea->uData.sSubAlloc.uiByteOffset = uiByteOffset;
+    psLinuxMemArea->uiByteSize = uBytes;
+    psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
+    psLinuxMemArea->bNeedsCacheInvalidate = psParentLinuxMemArea->bNeedsCacheInvalidate;
+    INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+    
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+        DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+        psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+        PVR_ASSERT(psParentRecord != IMG_NULL);
+        DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags);
+    }
+#endif
+    
+    return psLinuxMemArea;
+}
+
+
+static IMG_VOID
+FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+    
+    /* Nothing more to do than free the LinuxMemArea structure */
+
+    LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static LinuxMemArea *
+LinuxMemAreaStructAlloc(IMG_VOID)
+{
+/* debug */
+#if 0
+    LinuxMemArea *psLinuxMemArea;
+    psLinuxMemArea = kmem_cache_alloc(g_PsLinuxMemAreaCache, GFP_KERNEL);
+    printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
+    dump_stack();
+    return psLinuxMemArea;
+#else
+    return KMemCacheAllocWrapper(g_PsLinuxMemAreaCache, GFP_KERNEL);
+#endif
+}
+
+
+static IMG_VOID
+LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
+{
+    KMemCacheFreeWrapper(g_PsLinuxMemAreaCache, psLinuxMemArea);
+    /* debug */
+    //printk(KERN_ERR "%s(%p)\n", __FUNCTION__, psLinuxMemArea);
+}
+
+
+IMG_VOID
+LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
+{
+    switch (psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_VMALLOC:
+            FreeVMallocLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            FreeAllocPagesLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_IOREMAP:
+            FreeIORemapLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_EXTERNAL_KV:
+            FreeExternalKVLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_IO:
+            FreeIOLinuxMemArea(psLinuxMemArea);
+            break;
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            FreeSubLinuxMemArea(psLinuxMemArea);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+            break;
+    }
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID
+DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+    const IMG_CHAR *pi8FlagsString;
+    
+    LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
+
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_LinuxMemAreaWaterMark += psLinuxMemArea->uiByteSize;
+        if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+        {
+            g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
+        }
+    }
+    g_LinuxMemAreaCount++;
+    
+    /* Create a new memory allocation record */
+    psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
+    if (psNewRecord)
+    {
+        /* Record the allocation */
+        psNewRecord->psLinuxMemArea = psLinuxMemArea;
+        psNewRecord->ui32Flags = ui32Flags;
+        psNewRecord->pid = OSGetCurrentProcessIDKM();
+		
+		List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                 "%s: failed to allocate linux memory area record.",
+                 __FUNCTION__));
+    }
+    
+    /* Sanity check the flags */
+    pi8FlagsString = HAPFlagsToString(ui32Flags);
+    if (strstr(pi8FlagsString, "UNKNOWN"))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+                 "%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p",
+                 __FUNCTION__,
+                 ui32Flags,
+                 psLinuxMemArea));
+        //dump_stack();
+    }
+
+    LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+
+static IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord,
+										   va_list va)
+{
+	LinuxMemArea *psLinuxMemArea;
+	
+	psLinuxMemArea = va_arg(va, LinuxMemArea*);
+	if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+	{
+		return psCurrentRecord;
+	}
+	else
+	{
+		return IMG_NULL;
+	}
+}
+
+
+static DEBUG_LINUX_MEM_AREA_REC *
+DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+    LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
+	psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+														MatchLinuxMemArea_AnyVaCb,
+														psLinuxMemArea);
+	
+/*exit_unlock:*/
+    LinuxUnLockMutex(&g_sDebugMutex);
+
+    return psCurrentRecord;
+}
+
+
+static IMG_VOID
+DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+    LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);
+
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_LinuxMemAreaWaterMark -= psLinuxMemArea->uiByteSize;
+    }
+    g_LinuxMemAreaCount--;
+
+    /* Locate the corresponding allocation entry */
+	psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+														MatchLinuxMemArea_AnyVaCb,
+														psLinuxMemArea);
+	if (psCurrentRecord)
+	{
+		/* Unlink the allocation record */
+		List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
+		kfree(psCurrentRecord);
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n",
+        	     __FUNCTION__, psLinuxMemArea));
+	}
+
+    LinuxUnLockMutex(&g_sDebugMutex);
+}
+#endif
+
+
+IMG_VOID *
+LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
+{
+    switch (psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_VMALLOC:
+            return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+        case LINUX_MEM_AREA_IOREMAP:
+            return psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	    return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+            IMG_CHAR *pAddr =
+                LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea); /* PRQA S 3670 */ /* ignore recursive warning */
+            if (!pAddr)
+            {
+                return NULL;
+            }
+            return pAddr + psLinuxMemArea->uData.sSubAlloc.uiByteOffset;
+        }
+        default:
+            return NULL;
+    }
+}
+
+
+IMG_CPU_PHYADDR
+LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uiByteOffset)
+{
+    IMG_CPU_PHYADDR CpuPAddr;
+    
+    CpuPAddr.uiAddr = 0;
+
+    switch (psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+        {
+            CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
+            CpuPAddr.uiAddr += uiByteOffset;
+            break;
+        }
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	{
+	    if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+	    {
+		CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+		CpuPAddr.uiAddr += uiByteOffset;
+	    }
+	    else
+	    {
+		IMG_UINTPTR_T uiPageIndex = PHYS_TO_PFN(uiByteOffset);
+		IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[uiPageIndex];
+
+		CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+                CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(uiByteOffset);
+	    }
+            break;
+	}
+        case LINUX_MEM_AREA_IO:
+        {
+            CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
+            CpuPAddr.uiAddr += uiByteOffset;
+            break;
+        }
+        case LINUX_MEM_AREA_VMALLOC:
+        {
+            IMG_CHAR *pCpuVAddr;
+            pCpuVAddr =
+                (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+            pCpuVAddr += uiByteOffset;
+            CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
+            break;
+        }
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+        {
+            struct page *page;
+            IMG_UINTPTR_T uiPageIndex = PHYS_TO_PFN(uiByteOffset);
+            page = psLinuxMemArea->uData.sPageList.ppsPageList[uiPageIndex];
+            CpuPAddr.uiAddr = page_to_phys(page);
+            CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(uiByteOffset);
+            break;
+        }
+        case LINUX_MEM_AREA_SUB_ALLOC:
+        {
+            CpuPAddr =
+                OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+                                      psLinuxMemArea->uData.sSubAlloc.uiByteOffset
+                                        + uiByteOffset);
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+            PVR_ASSERT(CpuPAddr.uiAddr);
+           break;
+        }
+   }
+    
+    return CpuPAddr;
+}
+
+
+IMG_BOOL
+LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
+{
+    switch (psLinuxMemArea->eAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+        case LINUX_MEM_AREA_IO:
+            return IMG_TRUE;
+
+        case LINUX_MEM_AREA_EXTERNAL_KV:
+            return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+        case LINUX_MEM_AREA_VMALLOC:
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            return IMG_FALSE;
+
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            /* PRQA S 3670 1 */ /* ignore recursive warning */
+            return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+                     __FUNCTION__, psLinuxMemArea->eAreaType));
+	    break;
+    }
+    return IMG_FALSE;
+}
+
+
+const IMG_CHAR *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+    /* Note we explicitly check the types instead of e.g.
+     * using the type to index an array of strings so
+     * we remain orthogonal to enum changes */
+    switch (eMemAreaType)
+    {
+        case LINUX_MEM_AREA_IOREMAP:
+            return "LINUX_MEM_AREA_IOREMAP";
+	case LINUX_MEM_AREA_EXTERNAL_KV:
+	    return "LINUX_MEM_AREA_EXTERNAL_KV";
+        case LINUX_MEM_AREA_IO:
+            return "LINUX_MEM_AREA_IO";
+        case LINUX_MEM_AREA_VMALLOC:
+            return "LINUX_MEM_AREA_VMALLOC";
+        case LINUX_MEM_AREA_SUB_ALLOC:
+            return "LINUX_MEM_AREA_SUB_ALLOC";
+        case LINUX_MEM_AREA_ALLOC_PAGES:
+            return "LINUX_MEM_AREA_ALLOC_PAGES";
+        default:
+            PVR_ASSERT(0);
+    }
+
+    return "";
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start) 
+{
+	if (start) 
+	{
+	    LinuxLockMutexNested(&g_sDebugMutex, PVRSRV_LOCK_CLASS_MM_DEBUG);		
+	}
+	else
+	{
+	    LinuxUnLockMutex(&g_sDebugMutex);
+	}
+}
+#endif /* defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+
+static IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va)
+{
+	off_t *pOff = va_arg(va, off_t*);
+	if (--(*pOff))
+	{
+		return IMG_NULL;
+	}
+	else
+	{
+		return psNode;
+	}
+}
+
+/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */ 
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off) 
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord;
+	psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+				List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+													DecOffMemAreaRec_AnyVaCb,
+													&off);
+	return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord;
+	if (!off) 
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+	psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+				List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+													DecOffMemAreaRec_AnyVaCb,
+													&off);
+	return (void*)psRecord;
+}
+
+
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
+{
+    DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el; 
+	if (el == PVR_PROC_SEQ_START_TOKEN) 
+	{
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+        seq_printf(sfile,
+              			  "Number of Linux Memory Areas: %u\n"
+                          "At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n"
+                          "At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n"
+                          "\nDetails for all Linux Memory Areas:\n"
+                          "%s %-24s %s %s %-8s %-5s %s\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark,
+                          "psLinuxMemArea",
+                          "LinuxMemType",
+                          "CpuVAddr",
+                          "CpuPAddr",
+                          "Bytes",
+                          "Pid",
+                          "Flags"
+                        );
+#else
+        seq_printf(sfile,
+                          "<mem_areas_header>\n"
+                          "\t<count>%u</count>\n"
+                          "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */
+                          "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */
+                          "</mem_areas_header>\n",
+                          g_LinuxMemAreaCount,
+                          g_LinuxMemAreaWaterMark,
+                          g_LinuxMemAreaHighWaterMark
+                        );
+#endif
+		return;
+	}
+
+        seq_printf(sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                       "%p       %-24s %p " CPUPADDR_FMT " %" SIZE_T_FMT_LEN "u %-5u %08x=(%s)\n",
+#else
+                       "<linux_mem_area>\n"
+                       "\t<pointer>%p</pointer>\n"
+                       "\t<type>%s</type>\n"
+                       "\t<cpu_virtual>%p</cpu_virtual>\n"
+                       "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+                       "\t<bytes>%" SIZE_T_FMT_LEN "d</bytes>\n"
+                       "\t<pid>%u</pid>\n"
+                       "\t<flags>%08x</flags>\n"
+                       "\t<flags_string>%s</flags_string>\n"
+                       "</linux_mem_area>\n",
+#endif
+                       psRecord->psLinuxMemArea,
+                       LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+                       LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+                       LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+                       psRecord->psLinuxMemArea->uiByteSize,
+                       psRecord->pid,
+                       psRecord->ui32Flags,
+                       HAPFlagsToString(psRecord->ui32Flags)
+                     );
+
+}
+#endif /* DEBUG_LINUX_MEM_AREAS */
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+
+static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va)
+{
+	off_t *pOff = va_arg(va, off_t*);
+	if (--(*pOff))
+	{
+		return IMG_NULL;
+	}
+	else
+	{
+		return psNode;
+	}
+}
+
+/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */ 
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off) 
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+	psRecord = (DEBUG_MEM_ALLOC_REC*)
+		List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+										DecOffMemAllocRec_AnyVaCb,
+										&off);
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+	if (!psRecord) 
+	{
+		seq_printf(sfile, "</meminfo>\n");
+	}
+#endif
+
+	return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord;
+	if (!off) 
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+	psRecord = (DEBUG_MEM_ALLOC_REC*)
+		List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+										DecOffMemAllocRec_AnyVaCb,
+										&off);
+
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+	if (!psRecord) 
+	{
+		seq_printf(sfile, "</meminfo>\n");
+	}
+#endif
+
+	return (void*)psRecord;
+}
+
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
+{
+    DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
+	if (el == PVR_PROC_SEQ_START_TOKEN) 
+	{
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+        /* NOTE: If you update this code, please also update the XML varient below
+         * too! */
+
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via kmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC] + g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_SWAP]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via kmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC] + g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_SWAP]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via vmalloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via vmalloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via alloc_pages",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via alloc_pages",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via ioremap",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via ioremap",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes reserved for \"IO\" memory areas",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Current Water Mark of bytes mapped via vmap",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "Highest Water Mark of bytes mapped via vmap",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+        seq_printf(sfile, "%-60s: %d pages\n",
+                           "Number of pages in page pool",
+                           atomic_read(&g_sPagePoolEntryCount));
+#endif
+        seq_printf( sfile, "\n");
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "The Current Water Mark for memory allocated from system RAM",
+                           SysRAMTrueWaterMark());
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "The Highest Water Mark for memory allocated from system RAM",
+                           g_SysRAMHighWaterMark);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "The Current Water Mark for memory allocated from IO memory",
+                           g_IOMemWaterMark);
+        seq_printf(sfile, "%-60s: %d bytes\n",
+                           "The Highest Water Mark for memory allocated from IO memory",
+                           g_IOMemHighWaterMark);
+
+        seq_printf( sfile, "\n");
+
+		seq_printf(sfile, "Details for all known allocations:\n"
+                           "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+                           "Type",
+                           "CpuVAddr",
+                           "CpuPAddr",
+                           "Bytes",
+                           "PID",
+                           "PrivateData",
+                           "Filename:Line");
+
+#else /* DEBUG_LINUX_XML_PROC_FILES */
+		
+		/* Note: If you want to update the description property of a watermark
+		 * ensure that the key property remains unchanged so that watermark data
+		 * logged over time from different driver revisions may remain comparable
+		 */
+		seq_printf(sfile, "<meminfo>\n<meminfo_header>\n");
+		seq_printf(sfile,
+                           "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC] +  g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_SWAP]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC] +  g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_SWAP]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+		seq_printf(sfile,
+                           "<watermark key=\"mr12\" description=\"vmap_current\" bytes=\"%d\"/>\n",
+                           g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+		seq_printf(sfile,
+                           "<watermark key=\"mr13\" description=\"vmap_high\" bytes=\"%d\"/>\n",
+                           g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+		seq_printf(sfile,
+                           "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n",
+                           SysRAMTrueWaterMark());
+		seq_printf(sfile,
+                           "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n",
+                           g_SysRAMHighWaterMark);
+		seq_printf(sfile,
+                           "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n",
+                           g_IOMemWaterMark);
+		seq_printf(sfile,
+                           "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n",
+                           g_IOMemHighWaterMark);
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+		seq_printf(sfile,
+                           "<watermark key=\"mr18\" description=\"page_pool_current\" bytes=\"%d\"/>\n",
+                           PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount)));
+#endif
+		seq_printf(sfile, "</meminfo_header>\n");
+
+#endif /* DEBUG_LINUX_XML_PROC_FILES */
+		return;
+	}
+
+    if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+    {
+		seq_printf(sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %p " CPUPADDR_FMT " %" SIZE_T_FMT_LEN "u %-5d %-10s %s:%d\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%p</cpu_virtual>\n"
+                           "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+                           "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%d</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->sCpuPAddr.uiAddr,
+                           psRecord->uiBytes,
+                           psRecord->pid,
+                           "NULL",
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+    else
+    {
+		seq_printf(sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+                           "%-16s %p " CPUPADDR_FMT " %" SIZE_T_FMT_LEN "u %-5d %-10s %s:%d\n",
+#else
+                           "<allocation>\n"
+                           "\t<type>%s</type>\n"
+                           "\t<cpu_virtual>%p</cpu_virtual>\n"
+                           "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+                           "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
+                           "\t<pid>%d</pid>\n"
+                           "\t<private>%s</private>\n"
+                           "\t<filename>%s</filename>\n"
+                           "\t<line>%d</line>\n"
+                           "</allocation>\n",
+#endif
+                           DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+                           psRecord->pvCpuVAddr,
+                           psRecord->sCpuPAddr.uiAddr,
+                           psRecord->uiBytes,
+                           psRecord->pid,
+                           KMemCacheNameWrapper(psRecord->pvPrivateData),
+                           psRecord->pszFileName,
+                           psRecord->ui32Line);
+    }
+}
+#endif /*  defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+/* This could be moved somewhere more general */
+const IMG_CHAR *
+HAPFlagsToString(IMG_UINT32 ui32Flags)
+{
+    static IMG_CHAR szFlags[50];
+    IMG_INT32 i32Pos = 0;
+    IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex;
+    IMG_CHAR *apszCacheTypes[] = {
+        "UNCACHED",
+        "CACHED",
+        "WRITECOMBINE",
+        "UNKNOWN"
+    };
+    IMG_CHAR *apszMapType[] = {
+        "KERNEL_ONLY",
+        "SINGLE_PROCESS",
+        "MULTI_PROCESS",
+        "FROM_EXISTING_PROCESS",
+        "NO_CPU_VIRTUAL",
+        "UNKNOWN"
+    };
+    
+    /* FIXME create an enum for the cache type that we can
+     * cast and select so we get compiler warnings when
+     * when this code isn't complete due to new flags */
+    if (ui32Flags & PVRSRV_HAP_UNCACHED) {
+        ui32CacheTypeIndex = 0;
+    } else if (ui32Flags & PVRSRV_HAP_CACHED) {
+        ui32CacheTypeIndex = 1;
+    } else if (ui32Flags & PVRSRV_HAP_WRITECOMBINE) {
+        ui32CacheTypeIndex = 2;
+    } else {
+        ui32CacheTypeIndex = 3;
+        PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
+                 __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
+    }
+
+    /* FIXME create an enum for the map type that we can
+     * cast and select so we get compiler warnings when
+     * when this code isn't complete due to new flags */
+    if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) {
+        ui32MapTypeIndex = 0;
+    } else if (ui32Flags & PVRSRV_HAP_SINGLE_PROCESS) {
+        ui32MapTypeIndex = 1;
+    } else if (ui32Flags & PVRSRV_HAP_MULTI_PROCESS) {
+        ui32MapTypeIndex = 2;
+    } else if (ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS) {
+        ui32MapTypeIndex = 3;
+    } else if (ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL) {
+        ui32MapTypeIndex = 4;
+    } else {
+        ui32MapTypeIndex = 5;
+        PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
+                 __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
+    }
+
+    i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+    if (i32Pos <= 0)
+    {
+	PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)",
+		__FUNCTION__, ui32CacheTypeIndex, i32Pos));
+	szFlags[0] = 0;
+    }
+    else
+    {
+        sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+    }
+
+    return szFlags;
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+	LinuxMemArea *psLinuxMemArea;
+
+	psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+	PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%"SIZE_T_FMT_LEN"d bytes",
+				__FUNCTION__,
+				psCurrentRecord->psLinuxMemArea,
+				LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+				psCurrentRecord->psLinuxMemArea->uiByteSize));
+	/* Note this will also remove psCurrentRecord from g_LinuxMemAreaRecords
+	 * but that's ok since we have already got a pointer to the next area. */
+	LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+	
+/* It's a bug if anything remains allocated at this point. We
+ * report an error, and simply brute force free anything we find. */
+	PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+							"type=%s "
+							"CpuVAddr=%p "
+							"CpuPAddr=0x" CPUPADDR_FMT ", "
+							"allocated @ file=%s,line=%d",
+			__FUNCTION__,
+			DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+			psCurrentRecord->pvCpuVAddr,
+			psCurrentRecord->sCpuPAddr.uiAddr,
+			psCurrentRecord->pszFileName,
+			psCurrentRecord->ui32Line));
+	switch (psCurrentRecord->eAllocType)
+	{
+		case DEBUG_MEM_ALLOC_TYPE_SWAP:
+			_KFreeWrapper(psCurrentRecord->pvCpuVAddr, __FILE__, __LINE__, IMG_TRUE);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+			KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+			IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_IO:
+			/* Nothing needed except to free the record */
+			DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->uiKey, __FILE__, __LINE__);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+			VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+			DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->uiKey, __FILE__, __LINE__);
+			break;
+		case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+			KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
+			break;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+		case DEBUG_MEM_ALLOC_TYPE_VMAP:
+			VUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+			break;
+#endif
+		default:
+			PVR_ASSERT(0);
+	}
+}
+#endif
+
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
+static int
+ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+	if(psShrinkControl->nr_to_scan != 0)
+	{
+		return ScanObjectsInPagePool(psShrinker, psShrinkControl);
+	}
+	else
+	{
+		/* No pages are being reclaimed so just return the page count. */
+		return CountObjectsInPagePool(psShrinker, psShrinkControl);
+	}
+}
+
+static struct shrinker g_sShrinker =
+{
+        .shrink = ShrinkPagePool,
+        .seeks = DEFAULT_SEEKS
+};
+#else
+static struct shrinker g_sShrinker = 
+{
+	.count_objects = CountObjectsInPagePool,
+	.scan_objects = ScanObjectsInPagePool,
+	.seeks = DEFAULT_SEEKS 
+};
+#endif
+
+static IMG_BOOL g_bShrinkerRegistered;
+#endif
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+        if (g_LinuxMemAreaCount)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
+                    __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+        }
+		
+	List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords, LinuxMMCleanup_MemAreas_ForEachCb);
+
+	if (g_SeqFileMemArea)
+	{
+	    RemoveProcEntrySeq(g_SeqFileMemArea);
+	}
+    }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+	if (g_bShrinkerRegistered)
+	{
+		unregister_shrinker(&g_sShrinker);
+	}
+#endif
+
+    /*
+     * The page pool must be freed after any remaining mem areas, but before
+     * the remaining memory resources.
+     */
+    FreePagePool();
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    {
+        
+        /*
+	 * It's a bug if anything remains allocated at this point. We
+         * report an error, and simply brute force free anything we find.
+	 */
+		List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords, LinuxMMCleanup_MemRecords_ForEachVa);
+		List_DEBUG_MEM_ALLOC_REC_ForEach(g_SwapMemoryRecords, LinuxMMCleanup_MemRecords_ForEachVa);
+
+		if (g_SeqFileMemoryRecords)
+		{
+			RemoveProcEntrySeq(g_SeqFileMemoryRecords);
+		}
+    }
+#endif
+
+    if (g_PsLinuxMemAreaCache)
+    {
+        KMemCacheDestroyWrapper(g_PsLinuxMemAreaCache); 
+    }
+
+    if (g_PsLinuxPagePoolCache)
+    {
+        KMemCacheDestroyWrapper(g_PsLinuxPagePoolCache); 
+    }
+}
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	LinuxInitMutex(&g_sDebugMutex);
+	LinuxInitMutex(&g_sSwapDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+    {
+		g_SeqFileMemArea = CreateProcReadEntrySeq(
+									"mem_areas", 
+									NULL, 
+									ProcSeqNextMemArea,
+									ProcSeqShowMemArea,
+									ProcSeqOff2ElementMemArea,
+									ProcSeqStartstopDebugMutex
+								  );
+		if (!g_SeqFileMemArea)
+		{
+		    goto failed;
+		}
+    }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    {
+		g_SeqFileMemoryRecords = CreateProcReadEntrySeq(
+									"meminfo", 
+									NULL, 
+									ProcSeqNextMemoryRecords,
+									ProcSeqShowMemoryRecords, 
+									ProcSeqOff2ElementMemoryRecords,
+									ProcSeqStartstopDebugMutex
+								  );
+        	if (!g_SeqFileMemoryRecords)
+		{
+		    goto failed;
+		}
+    }
+#endif
+
+    g_PsLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+    if (!g_PsLinuxMemAreaCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate mem area kmem_cache", __FUNCTION__));
+        goto failed;
+    }
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+    g_iPagePoolMaxEntries = PVR_LINUX_MEM_AREA_POOL_MAX_PAGES;
+    if (g_iPagePoolMaxEntries <= 0 || g_iPagePoolMaxEntries > INT_MAX/2)
+    {
+	g_iPagePoolMaxEntries = INT_MAX/2;
+	PVR_TRACE(("%s: No limit set for page pool size", __FUNCTION__));
+    }
+    else
+    {
+	PVR_TRACE(("%s: Maximum page pool size: %d", __FUNCTION__, g_iPagePoolMaxEntries));
+    }
+
+    g_PsLinuxPagePoolCache = KMemCacheCreateWrapper("img-mm-pool", sizeof(LinuxPagePoolEntry), 0, 0);
+    if (!g_PsLinuxPagePoolCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate page pool kmem_cache", __FUNCTION__));
+        goto failed;
+    }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+	register_shrinker(&g_sShrinker);
+	g_bShrinkerRegistered = IMG_TRUE;
+#endif
+
+    return PVRSRV_OK;
+
+failed:
+    LinuxMMCleanup();
+    return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mm.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.h
new file mode 100644
index 0000000..4e64dd6
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mm.h
@@ -0,0 +1,675 @@
+/*************************************************************************/ /*!
+@Title          Linux Memory Management.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declares various memory management utility functions
+                for Linux.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <asm/io.h>
+
+#define	PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define	ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+#define	PAGES_TO_BYTES(pages) ((pages) << PAGE_SHIFT)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define	REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define	REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+#define	IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define	IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#define	VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot);
+#else
+#define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot);
+#endif
+#endif
+
+static inline IMG_UINTPTR_T VMallocToPhys(IMG_VOID *pCpuVAddr)
+{
+	return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+		
+}
+
+typedef enum {
+    LINUX_MEM_AREA_IOREMAP,
+    LINUX_MEM_AREA_EXTERNAL_KV,
+    LINUX_MEM_AREA_IO,
+    LINUX_MEM_AREA_VMALLOC,
+    LINUX_MEM_AREA_ALLOC_PAGES,
+    LINUX_MEM_AREA_SUB_ALLOC,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+    LINUX_MEM_AREA_VMAP,
+#endif
+    LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+/* FIXME - describe this structure. */
+struct _LinuxMemArea {
+    LINUX_MEM_AREA_TYPE eAreaType;
+    union _uData
+    {
+        struct _sIORemap
+        {
+            /* Note: The memory this represents is _not_ implicitly
+             * page aligned, neither is its size */
+            IMG_CPU_PHYADDR CPUPhysAddr;
+            IMG_VOID *pvIORemapCookie;
+        }sIORemap;
+        struct _sExternalKV
+        {
+            /* Note: The memory this represents is _not_ implicitly
+             * page aligned, neither is its size */
+	    IMG_BOOL bPhysContig;
+	    union {
+		    /*
+		     * SYSPhysAddr is valid if bPhysContig is true, else
+		     * pSysPhysAddr is valid
+		     */
+		    IMG_SYS_PHYADDR SysPhysAddr;
+		    IMG_SYS_PHYADDR *pSysPhysAddr;
+	    } uPhysAddr;
+            IMG_VOID *pvExternalKV;
+        }sExternalKV;
+        struct _sIO
+        {
+            /* Note: The memory this represents is _not_ implicitly
+             * page aligned, neither is its size */
+            IMG_CPU_PHYADDR CPUPhysAddr;
+        }sIO;
+        struct _sVmalloc
+        {
+            /* Note the memory this represents _is_ implicitly
+             * page aligned _and_ so is its size */
+            IMG_VOID *pvVmallocAddress;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+            struct page **ppsPageList;
+	    IMG_HANDLE hBlockPageList;
+#endif
+        }sVmalloc;
+        struct _sPageList
+        {
+            /* Note the memory this represents _is_ implicitly
+             * page aligned _and_ so is its size */
+            struct page **ppsPageList;
+	    IMG_HANDLE hBlockPageList;
+        }sPageList;
+        struct _sSubAlloc
+        {
+            /* Note: The memory this represents is _not_ implicitly
+             * page aligned, neither is its size */
+            LinuxMemArea *psParentLinuxMemArea;
+            IMG_UINTPTR_T uiByteOffset;
+        }sSubAlloc;
+    }uData;
+
+    IMG_SIZE_T uiByteSize;		    /* Size of memory area */
+
+    IMG_UINT32 ui32AreaFlags;		/* Flags passed at creation time */
+
+    IMG_BOOL bMMapRegistered;		/* Registered with mmap code */
+
+    IMG_BOOL bNeedsCacheInvalidate;	/* Cache should be invalidated on first map? */
+
+	IMG_HANDLE hBMHandle;			/* Handle back to BM for this allocation */
+
+    /* List entry for global list of areas registered for mmap */
+    struct list_head	sMMapItem;
+
+    /*
+     * Head of list of all mmap offset structures associated with this
+     * memory area.
+     */
+    struct list_head	sMMapOffsetStructList;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+typedef kmem_cache_t LinuxKMemCache;
+#else
+typedef struct kmem_cache LinuxKMemCache;
+#endif
+
+
+/*!
+ *******************************************************************************
+ * @Function	LinuxMMInit
+ *
+ * @Description
+ *
+ * Initialise linux memory management code.
+ * This should be called during services initialisation.
+ *
+ * @Return none
+******************************************************************************/
+PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+
+
+/*!
+ *******************************************************************************
+ *
+ * @Function	LinuxMMCleanup
+ *
+ * @Description
+ *
+ * Cleanup state for the linux memory management code.
+ * This should be called at services cleanup.
+ *
+ * @Return none
+******************************************************************************/
+IMG_VOID LinuxMMCleanup(IMG_VOID);
+
+
+/*!
+ *******************************************************************************
+ * @brief Wrappers for kmalloc/kfree with optional /proc/pvr/km tracking
+ *        They can also be used as more concise replacements for OSAllocMem
+ *        in Linux specific code.
+ *
+ * @param uByteSize  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMallocWrapper(uByteSize, uFlags) _KMallocWrapper(uByteSize, uFlags, __FILE__, __LINE__, IMG_FALSE)
+#else
+#define KMallocWrapper(uByteSize, uFlags) _KMallocWrapper(uByteSize, uFlags, NULL, 0, IMG_FALSE)
+#endif
+void *_KMallocWrapper(IMG_SIZE_T uByteSize, gfp_t uFlags, IMG_CHAR *szFileName, IMG_UINT32 ui32Line, IMG_BOOL bSwapAlloc);
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param pvCpuVAddr  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__, IMG_FALSE)
+#else
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0, IMG_FALSE)
+#endif
+void _KFreeWrapper(void *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line, IMG_BOOL bSwapAlloc);
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param uBytes  
+ * @param ui32AllocFlags  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMallocWrapper(uiBytes, ui32AllocFlags) _VMallocWrapper(uiBytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMallocWrapper(uiBytes, ui32AllocFlags) _VMallocWrapper(uiBytes, ui32AllocFlags, NULL, 0)
+#endif
+IMG_VOID *_VMallocWrapper(IMG_SIZE_T uiBytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param pvCpuVAddr  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+/*!
+ *******************************************************************************
+ * @brief Allocates virtually contiguous pages
+ *
+ * @param uBytes  number of bytes to reserve
+ * @param ui32AreaFlags  Heap caching and mapping Flags
+ *
+ * @return Page-aligned address of virtual allocation or NULL on error
+ ******************************************************************************/
+LinuxMemArea *NewVMallocLinuxMemArea(IMG_SIZE_T uBytes, IMG_UINT32 ui32AreaFlags);
+
+
+/*!
+ *******************************************************************************
+ * @brief Deallocates virtually contiguous pages
+ *
+ * @param LinuxMemArea from NewVMallocLinuxMemArea
+ *
+ ******************************************************************************/
+IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ *******************************************************************************
+ * @brief Reserve physical IO memory and create a CPU virtual mapping for it
+ *
+ * @param BasePAddr 
+ * @param uiBytes  
+ * @param ui32MappingFlags  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags) \
+    _IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags) \
+    _IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags, NULL, 0)
+#endif
+IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+                          IMG_SIZE_T uiBytes,
+                          IMG_UINT32 ui32MappingFlags,
+                          IMG_CHAR *pszFileName,
+                          IMG_UINT32 ui32Line);
+
+
+/*!
+ *******************************************************************************
+ * @brief Reserve physical IO memory and create a CPU virtual mapping for it
+ *
+ * @param BasePAddr  
+ * @param uiBytes  
+ * @param ui32AreaFlags  Heap caching and mapping Flags
+ *
+ * @return 
+ ******************************************************************************/
+LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T uiBytes, IMG_UINT32 ui32AreaFlags);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return 
+ ********************************************************************************/
+IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+/*!
+ *******************************************************************************
+ * @brief Register physical memory which already has a CPU virtual mapping
+ *
+ * @param pBasePAddr  
+ * @param pvCPUVAddr  
+ * @param bPhysContig
+ * @param uBytes  
+ * @param ui32AreaFlags  Heap caching and mapping Flags
+ *
+ * @return 
+ ******************************************************************************/
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_SIZE_T uBytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return 
+ ******************************************************************************/
+IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ ******************************************************************************
+ * @brief Unmaps an IO memory mapping created using IORemap
+ *
+ * @param pvIORemapCookie  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+    _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+    _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ * @param uByteOffset  
+ *
+ * @return 
+ ******************************************************************************/
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uByteOffset);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param pszName  
+ * @param Size  
+ * @param Align  
+ * @param ui32Flags  
+ *
+ * @return 
+ ******************************************************************************/
+LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psCache  
+ *
+ * @return 
+ ******************************************************************************/
+IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psCache  
+ * @param Flags  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
+#else
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#else
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#endif
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psCache  
+ * @param pvObject  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
+#else
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
+#endif
+IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psCache  
+ *
+ * @return 
+ ******************************************************************************/
+const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param BasePAddr  
+ * @param uiBytes  
+ * @param ui32AreaFlags  Heap caching and mapping Flags
+ *
+ * @return 
+ ******************************************************************************/
+LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T uiBytes, IMG_UINT32 ui32AreaFlags);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return 
+ ******************************************************************************/
+IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param uiBytes  
+ * @param ui32AreaFlags  E.g Heap caching and mapping Flags
+ *
+ * @return 
+ ******************************************************************************/
+LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_SIZE_T uiBytes, IMG_UINT32 ui32AreaFlags);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return 
+ ******************************************************************************/
+IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psParentLinuxMemArea  
+ * @param uByteOffset
+ * @param uBytes
+ *
+ * @return 
+ ******************************************************************************/
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+                                 IMG_UINTPTR_T uByteOffset,
+                                 IMG_SIZE_T uBytes);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return 
+ ******************************************************************************/
+IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ *******************************************************************************
+ * @brief For debug builds, LinuxMemAreas are tracked in /proc
+ *
+ * @param psLinuxMemArea  
+ *
+ ******************************************************************************/
+#if defined(LINUX_MEM_AREAS_DEBUG)
+IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
+#else
+#define LinuxMemAreaRegister(X)
+#endif
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return 
+ ******************************************************************************/
+IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param psLinuxMemArea  
+ * @param uByteOffset  
+ *
+ * @return 
+ ******************************************************************************/
+IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uByteOffset);
+
+
+#define	 LinuxMemAreaToCpuPFN(psLinuxMemArea, uByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, uByteOffset).uiAddr)
+
+/*!
+ *******************************************************************************
+ * @brief Indicate whether a LinuxMemArea is physically contiguous
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return IMG_TRUE if the physical address range is contiguous, else IMG_FALSE
+ ******************************************************************************/
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+/*!
+ *******************************************************************************
+ * @brief Return the real underlying LinuxMemArea
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return The real underlying LinuxMemArea
+ ******************************************************************************/
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+    if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+    }
+    else
+    {
+        return psLinuxMemArea;
+    }
+}
+
+
+/*!
+ *******************************************************************************
+ * @brief Return type of  real underlying LinuxMemArea
+ *
+ * @param psLinuxMemArea  
+ *
+ * @return The areas eAreaType or for SUB areas; return the parents eAreaType.
+ ******************************************************************************/
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+/*!
+ *******************************************************************************
+ * @brief Converts the enum type of a LinuxMemArea to a const string
+ *
+ * @param eMemAreaType  
+ *
+ * @return const string representation of type
+ ******************************************************************************/
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+/*!
+ *******************************************************************************
+ * @brief 
+ *
+ * @param ui32Flags  
+ *
+ * @return 
+ ******************************************************************************/
+#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
+const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
+#endif
+
+#endif /* __IMG_LINUX_MM_H__ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c
new file mode 100644
index 0000000..3a2a16b
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.c
@@ -0,0 +1,1659 @@
+/*************************************************************************/ /*!
+@Title          Linux mmap interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+#include <linux/highmem.h>
+#endif
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <linux/sched.h>
+#include <asm/current.h>
+#endif
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
+#include <drm/drm_legacy.h>
+#endif
+#endif
+
+#ifdef CONFIG_ARCH_OMAP5
+#ifdef CONFIG_DSSCOMP
+#include <../drivers/staging/omapdrm/omap_dmm_tiler.h>
+#endif
+#endif
+
+#include "services_headers.h"
+
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "proc.h"
+#include "mutex.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
+static inline int drm_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	return drm_legacy_mmap(filp, vma);
+}
+#endif
+
+/* WARNING:
+ * The mmap code has its own mutex, to prevent a possible deadlock,
+ * when using gPVRSRVLock.
+ * The Linux kernel takes the mm->mmap_sem before calling the mmap
+ * entry points (PVRMMap, MMapVOpen, MMapVClose), but the ioctl
+ * entry point may take mm->mmap_sem during fault handling, or 
+ * before calling get_user_pages.  If gPVRSRVLock was used in the
+ * mmap entry points, a deadlock could result, due to the ioctl
+ * and mmap code taking the two locks in different orders.
+ * As a corollary to this, the mmap entry points must not call
+ * any driver code that relies on gPVRSRVLock is held.
+ */
+PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+static LinuxKMemCache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static IMG_UINT32 g_ui32RegisteredAreas = 0;
+static IMG_SIZE_T g_uiTotalByteSize = 0;
+#endif
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static struct pvr_proc_dir_entry *g_ProcMMap;
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Now that we are using mmap2 in srvclient, almost (*) the full 32
+ * bit offset is available.  The range of values is divided into two.
+ * The first part of the range, from FIRST_PHYSICAL_PFN to
+ * LAST_PHYSICAL_PFN, is for raw page mappings (VM_PFNMAP).  The
+ * resulting 43 bit (*) physical address range should be enough for
+ * the current range of processors we support.
+ *
+ * NB: (*) -- the above figures assume 4KB page size.  The offset
+ * argument to mmap2() is in units of 4,096 bytes regardless of page
+ * size.  Thus, we lose (PAGE_SHIFT-12) bits of resolution on other
+ * architectures.
+ *
+ * The second part of the range, from FIRST_SPECIAL_PFN to LAST_SPECIAL_PFN,
+ * is used for all other mappings.  These other mappings will always
+ * consist of pages with associated page structures, and need not
+ * represent a contiguous range of physical addresses.
+ *
+ */
+#define MMAP2_PGOFF_RESOLUTION (32-PAGE_SHIFT+12)
+#define RESERVED_PGOFF_BITS 1
+#define	MAX_MMAP_HANDLE		((1UL<<(MMAP2_PGOFF_RESOLUTION-RESERVED_PGOFF_BITS))-1)
+
+#define	FIRST_PHYSICAL_PFN	0
+#define	LAST_PHYSICAL_PFN	(FIRST_PHYSICAL_PFN + MAX_MMAP_HANDLE)
+#define	FIRST_SPECIAL_PFN	(LAST_PHYSICAL_PFN + 1)
+#define	LAST_SPECIAL_PFN	(FIRST_SPECIAL_PFN + MAX_MMAP_HANDLE)
+
+#else	/* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */
+
+/*
+ * Since we no longer have to worry about clashes with the mmap
+ * offsets used for pure PFN mappings (VM_PFNMAP), there is greater
+ * freedom in choosing the mmap handles.  This is useful if the
+ * mmap offset space has to be shared with another driver component.
+ */
+
+#if defined(PVR_MMAP_OFFSET_BASE)
+#define	FIRST_SPECIAL_PFN 	PVR_MMAP_OFFSET_BASE
+#else
+#define FIRST_SPECIAL_PFN_BASE 0x80000000UL
+#define FIRST_SPECIAL_PFN (FIRST_SPECIAL_PFN_BASE >> (PAGE_SHIFT - 12))
+#endif
+
+#if defined(PVR_NUM_MMAP_HANDLES)
+#define	MAX_MMAP_HANDLE		PVR_NUM_MMAP_HANDLES
+#else
+#define MAX_MMAP_HANDLE_BASE 0x7fffffffUL
+#define MAX_MMAP_HANDLE (MAX_MMAP_HANDLE_BASE >> (PAGE_SHIFT - 12))
+#endif
+
+#endif	/* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+	/* Unsigned, no need to compare >=0 */
+	return (/*(pfn >= FIRST_PHYSICAL_PFN) &&*/ (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+	/* Unsigned, no need to compare <=MAX_UINT */
+	return ((pfn >= FIRST_SPECIAL_PFN) /*&& (pfn <= LAST_SPECIAL_PFN)*/) ? IMG_TRUE : IMG_FALSE;
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+	if (PFNIsPhysical(pfn))
+	{
+		PVR_ASSERT(PFNIsPhysical(pfn));
+		return IMG_NULL;
+	}
+	return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+#endif
+
+static inline IMG_UINTPTR_T
+HandleToMMapOffset(IMG_HANDLE hHandle)
+{
+	IMG_UINTPTR_T ulHandle = (IMG_UINTPTR_T)hHandle;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+	if (PFNIsSpecial(ulHandle))
+	{
+		PVR_ASSERT(PFNIsSpecial(ulHandle));
+		return 0;
+	}
+#endif
+	return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Determine whether physical or special mappings will be used for
+ * a given memory area.  At present, this decision is made on
+ * whether the mapping represents a contiguous range of physical
+ * addresses, which is a requirement for raw page mappings (VM_PFNMAP).
+ * In the VMA structure for such a mapping, vm_pgoff is the PFN
+ * (page frame number, the physical address divided by the page size)
+ * of the first page in the VMA.  The second page is assumed to have
+ * PFN (vm_pgoff + 1), the third (vm_pgoff + 2) and so on.
+ */
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+    return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+	/*
+ 	 * The PID is the thread ID, as each thread is a
+ 	 * seperate process.
+ 	 */
+	return (IMG_UINT32)current->pid;
+}
+#endif
+
+/*
+ * Create an offset structure, which is used to hold per-process
+ * mmap data.
+ */
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINTPTR_T uiOffset, IMG_SIZE_T uiRealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8x)",
+             __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+    if(psOffsetStruct == IMG_NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+        return IMG_NULL;
+    }
+    
+    psOffsetStruct->uiMMapOffset = uiOffset;
+
+    psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+    psOffsetStruct->uiRealByteSize = uiRealByteSize;
+
+    /*
+     * We store the TID in case two threads within a process
+     * generate the same offset structure, and both end up on the
+     * list of structures waiting to be mapped, at the same time.
+     * This could happen if two sub areas within the same page are
+     * being mapped at the same time.
+     * The TID allows the mmap entry point to distinguish which
+     * mapping is being done by which thread.
+     */
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    psOffsetStruct->ui32TID = GetCurrentThreadID();
+#endif
+    psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    /* Extra entries to support proc filesystem debug info */
+    psOffsetStruct->pszName = pszName;
+#endif
+
+    list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+    return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+#ifdef DEBUG
+    IMG_CPU_PHYADDR CpuPAddr;
+    CpuPAddr = LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0);
+#endif
+
+    list_del(&psOffsetStruct->sAreaItem);
+
+    if (psOffsetStruct->bOnMMapList)
+    {
+        list_del(&psOffsetStruct->sMMapItem);
+    }
+
+#ifdef DEBUG
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+             "psLinuxMemArea=%p, CpuPAddr=0x" CPUPADDR_FMT, 
+			 __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             CpuPAddr.uiAddr));
+#endif
+    
+    KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+}
+
+
+/*
+ * There are no alignment constraints for mapping requests made by user
+ * mode Services.  For this, and potentially other reasons, the
+ * mapping created for a users request may look different to the
+ * original request in terms of size and alignment.
+ *
+ * This function determines an offset that the user can add to the mapping
+ * that is _actually_ created which will point to the memory they are
+ * _really_ interested in.
+ *
+ */
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+                               IMG_SIZE_T *puiRealByteSize,
+                               IMG_UINTPTR_T *puiByteOffset)
+{
+    IMG_UINTPTR_T uiPageAlignmentOffset;
+    IMG_CPU_PHYADDR CpuPAddr;
+    
+    CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+    uiPageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+    
+    *puiByteOffset = uiPageAlignmentOffset;
+
+    *puiRealByteSize = PAGE_ALIGN(psLinuxMemArea->uiByteSize + uiPageAlignmentOffset);
+}
+
+
+/*!
+ *******************************************************************************
+
+ @Function  PVRMMapOSMemHandleToMMapData
+
+ @Description
+
+ Determine various parameters needed to mmap a memory area, and to
+ locate the memory within the mapped area.
+
+ @input psPerProc : Per-process data.
+ @input hMHandle : Memory handle.
+ @input puiMMapOffset : pointer to location for returned mmap offset.
+ @input puiByteOffset : pointer to location for returned byte offset.
+ @input puiRealByteSize : pointer to location for returned real byte size.
+ @input puiUserVaddr : pointer to location for returned user mode address.
+
+ @output puiMMapOffset : points to mmap offset to be used in mmap2 sys call.
+ @output puiByteOffset : points to byte offset of start of memory
+			   within mapped area returned by mmap2.
+ @output puiRealByteSize : points to size of area to be mapped.
+ @output puiUserVAddr : points to user mode address of start of
+			  mapping, or 0 if it hasn't been mapped yet.
+
+ @Return PVRSRV_ERROR : PVRSRV_OK, or error code.
+
+ ******************************************************************************/
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                             IMG_HANDLE hMHandle,
+                             IMG_UINTPTR_T *puiMMapOffset,
+                             IMG_UINTPTR_T *puiByteOffset,
+                             IMG_SIZE_T *puiRealByteSize,
+                             IMG_UINTPTR_T *puiUserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+
+        goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+	/* Sparse mappings have to ask the BM for the virtual size */
+	if (psLinuxMemArea->hBMHandle)
+	{
+		*puiRealByteSize = BM_GetVirtualSize(psLinuxMemArea->hBMHandle);
+		*puiByteOffset = 0;
+	}
+	else
+	{
+		DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+										puiRealByteSize,
+										puiByteOffset);
+	}
+
+    /* Check whether this memory area has already been mapped */
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+        {
+			if (!psLinuxMemArea->hBMHandle)
+			{
+				PVR_ASSERT(*puiRealByteSize == psOffsetStruct->uiRealByteSize);
+			}
+	   /*
+	    * User mode locking is required to stop two threads racing to
+	    * map the same memory area.  The lock should prevent a
+	    * second thread retrieving mmap data for a given handle,
+	    * before the first thread has done the mmap.
+	    * Without locking, both threads may attempt the mmap,
+	    * and one of them will fail.
+	    */
+	   *puiMMapOffset = psOffsetStruct->uiMMapOffset;
+	   *puiUserVAddr = psOffsetStruct->uiUserVAddr;
+	   PVRSRVOffsetStructIncRef(psOffsetStruct);
+
+	   eError = PVRSRV_OK;
+	   goto exit_unlock;
+        }
+    }
+
+    /* Memory area won't have been mapped yet */
+    *puiUserVAddr = 0;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+    {
+        *puiMMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+        PVR_ASSERT(PFNIsPhysical(*puiMMapOffset));
+    }
+    else
+#endif
+    {
+        *puiMMapOffset = HandleToMMapOffset(hMHandle);
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+        PVR_ASSERT(PFNIsSpecial(*puiMMapOffset));
+#endif
+    }
+
+    psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *puiMMapOffset, *puiRealByteSize);
+    if (psOffsetStruct == IMG_NULL)
+    {
+        eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+	goto exit_unlock;
+    }
+
+    /*
+    * Offset structures representing physical mappings are added to
+    * a list, so that they can be located when the memory area is mapped.
+    */
+    list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+    psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+    PVRSRVOffsetStructIncRef(psOffsetStruct);
+
+    eError = PVRSRV_OK;
+
+	/* Need to scale up the offset to counter the shifting that
+	   is done in the mmap2() syscall, as it expects the pgoff
+	   argument to be in units of 4,096 bytes irrespective of
+	   page size */
+	*puiMMapOffset = *puiMMapOffset << (PAGE_SHIFT - 12);
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+/*!
+ *******************************************************************************
+
+ @Function  PVRMMapReleaseMMapData
+
+ @Description
+
+ Release mmap data.
+
+ @input psPerProc : Per-process data.
+ @input hMHandle : Memory handle.
+ @input pbMUnmap : pointer to location for munmap flag.
+ @input puiUserVAddr : pointer to location for user mode address of mapping.
+ @input puiByteSize : pointer to location for size of mapping.
+
+ @Output pbMUnmap : points to flag that indicates whether an munmap is
+		    required.
+ @output puiUserVAddr : points to user mode address to munmap.
+
+ @Return PVRSRV_ERROR : PVRSRV_OK, or error code.
+
+ ******************************************************************************/
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+				IMG_HANDLE hMHandle,
+				IMG_BOOL *pbMUnmap,
+				IMG_SIZE_T *puiRealByteSize,
+                IMG_UINTPTR_T *puiUserVAddr)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_HANDLE hOSMemHandle;
+    PVRSRV_ERROR eError;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+    PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+    eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+    if (eError != PVRSRV_OK)
+    {
+	PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+
+	goto exit_unlock;
+    }
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    /* Find the offset structure */
+    list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+        if (psOffsetStruct->ui32PID == ui32PID)
+        {
+	    if (psOffsetStruct->ui32RefCount == 0)
+	    {
+		PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area %p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+		eError = PVRSRV_ERROR_STILL_MAPPED;
+		goto exit_unlock;
+	    }
+
+	    PVRSRVOffsetStructDecRef(psOffsetStruct);
+
+	    *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->uiUserVAddr != 0));
+
+	    *puiUserVAddr = (*pbMUnmap) ? psOffsetStruct->uiUserVAddr : 0;
+	    *puiRealByteSize = (*pbMUnmap) ? psOffsetStruct->uiRealByteSize : 0;
+
+	    eError = PVRSRV_OK;
+	    goto exit_unlock;
+        }
+    }
+
+    /* MMap data not found */
+    PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %p (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+
+    eError =  PVRSRV_ERROR_MAPPING_NOT_FOUND;
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+
+    return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINTPTR_T uiOffset, IMG_SIZE_T uiRealByteSize)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    IMG_UINT32 ui32TID = GetCurrentThreadID();
+#endif
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+        if (uiOffset == psOffsetStruct->uiMMapOffset && uiRealByteSize == psOffsetStruct->uiRealByteSize && psOffsetStruct->ui32PID == ui32PID)
+        {
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+	    /*
+	     * If the offset is physical, make sure the thread IDs match,
+	     * as different threads may be mapping different memory areas
+	     * with the same offset.
+	     */
+	    if (!PFNIsPhysical(uiOffset) || psOffsetStruct->ui32TID == ui32TID)
+#endif
+	    {
+	        return psOffsetStruct;
+	    }
+        }
+    }
+
+    return IMG_NULL;
+}
+
+
+/*
+ * Map a memory area into user space.
+ * Note, the ui32ByteOffset is _not_ implicitly page aligned since
+ * LINUX_MEM_AREA_SUB_ALLOC LinuxMemAreas have no alignment constraints.
+ */
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+            struct vm_area_struct* ps_vma,
+            IMG_UINTPTR_T uiByteOffset)
+{
+    IMG_SIZE_T uiByteSize;
+
+	if ((psLinuxMemArea->hBMHandle) && (uiByteOffset != 0))
+	{
+		/* Partial mapping of sparse allocations should never happen */
+		return IMG_FALSE;
+	}
+
+    if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),		/* PRQA S 3670 */ /* allow recursion */
+                    ps_vma,
+                    psLinuxMemArea->uData.sSubAlloc.uiByteOffset + uiByteOffset);
+    }
+
+    /*
+     * Note that ui32ByteSize may be larger than the size of the memory
+     * area being mapped, as the former is a multiple of the page size.
+     */
+    uiByteSize = ps_vma->vm_end - ps_vma->vm_start;
+    PVR_ASSERT(ADDR_TO_PAGE_OFFSET(uiByteSize) == 0);
+
+#if defined (__sparc__)
+    /*
+     * For LINUX_MEM_AREA_EXTERNAL_KV, we don't know where the address range
+     * we are being asked to map has come from, that is, whether it is memory
+     * or I/O.  For all architectures other than SPARC, there is no distinction.
+     * Since we don't currently support SPARC, we won't worry about it.
+     */
+#error "SPARC not supported"
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    if (PFNIsPhysical(ps_vma->vm_pgoff))
+    {
+		IMG_INT result;
+
+		PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+		PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, uiByteOffset) == ps_vma->vm_pgoff);
+        /*
+	 * Since the memory is contiguous, we can map the whole range in one
+	 * go .
+	 */
+
+	PVR_ASSERT(psLinuxMemArea->hBMHandle == IMG_NULL);
+
+	result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, uiByteSize, ps_vma->vm_page_prot);
+
+        if(result == 0)
+        {
+            return IMG_TRUE;
+        }
+
+        PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+    }
+#endif
+
+    {
+	/*
+         * Memory may be non-contiguous, so we map the range page,
+	 * by page.  Since VM_PFNMAP mappings are assumed to be physically
+	 * contiguous, we can't legally use REMAP_PFN_RANGE (that is, we
+	 * could, but the resulting VMA may confuse other bits of the kernel
+	 * that attempt to interpret it).
+	 * The only alternative is to use VM_INSERT_PAGE, which requires
+	 * finding the page structure corresponding to each page, or
+	 * if mixed maps are supported (VM_MIXEDMAP), vm_insert_mixed.
+	 */
+        IMG_UINTPTR_T ulVMAPos;
+	IMG_UINTPTR_T uiByteEnd = uiByteOffset + uiByteSize;
+	IMG_UINTPTR_T uiPA;
+	IMG_UINTPTR_T uiAdjustedPA = uiByteOffset;
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+		IMG_BOOL bMixedMap = IMG_FALSE;
+#endif
+	/* First pass, validate the page frame numbers */
+	for(uiPA = uiByteOffset; uiPA < uiByteEnd; uiPA += PAGE_SIZE)
+	{
+		IMG_UINTPTR_T pfn;
+	    IMG_BOOL bMapPage = IMG_TRUE;
+
+		if (psLinuxMemArea->hBMHandle)
+		{
+			if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, uiPA))
+			{
+				bMapPage = IMG_FALSE;
+			}
+		}
+
+		if (bMapPage)
+		{
+			pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, uiAdjustedPA);
+			if (!pfn_valid(pfn))
+			{
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+					PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x" UINTPTR_FMT, __FUNCTION__, pfn));
+					return IMG_FALSE;
+#else
+			bMixedMap = IMG_TRUE;
+#endif
+			}
+		    else if (0 == page_count(pfn_to_page(pfn)))
+		    {
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+		        bMixedMap = IMG_TRUE;
+#endif
+		    }
+			uiAdjustedPA += PAGE_SIZE;
+		}
+	}
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+		if (bMixedMap)
+		{
+		        ps_vma->vm_flags |= VM_MIXEDMAP;
+		}
+#endif
+	/* Second pass, get the page structures and insert the pages */
+        ulVMAPos = ps_vma->vm_start;
+        uiAdjustedPA = uiByteOffset;
+	for(uiPA = uiByteOffset; uiPA < uiByteEnd; uiPA += PAGE_SIZE)
+	{
+	    IMG_UINTPTR_T pfn;
+	    IMG_INT result;
+	    IMG_BOOL bMapPage = IMG_TRUE;
+
+		if (psLinuxMemArea->hBMHandle)
+		{
+			/* We have a sparse allocation, check if this page should be mapped */
+			if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, uiPA))
+			{
+				bMapPage = IMG_FALSE;
+			}
+		}
+
+		if (bMapPage)
+		{
+			pfn =  LinuxMemAreaToCpuPFN(psLinuxMemArea, uiAdjustedPA);
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+		    if (bMixedMap)
+		    {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0))
+			pfn_t pfns = { pfn };
+
+			result = vm_insert_mixed(ps_vma, ulVMAPos, pfns);
+#else
+			result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
+#endif
+	                if(result != 0)
+	                {
+	                    PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
+	                    return IMG_FALSE;
+	                }
+		    }
+		    else
+#endif
+		    {
+				struct page *psPage;
+	
+		        PVR_ASSERT(pfn_valid(pfn));
+	
+		        psPage = pfn_to_page(pfn);
+	
+		        result = VM_INSERT_PAGE(ps_vma,  ulVMAPos, psPage);
+	                if(result != 0)
+	                {
+	                    PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+	                    return IMG_FALSE;
+	                }
+		    }
+		    uiAdjustedPA += PAGE_SIZE;
+			}
+	        ulVMAPos += PAGE_SIZE;
+		}
+	}
+
+    return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+
+    PVR_ASSERT(psOffsetStruct != IMG_NULL);
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+    PVRSRVOffsetStructIncMapped(psOffsetStruct);
+
+    if (psOffsetStruct->ui32Mapped > 1)
+    {
+	PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+        PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+    }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset " UINTPTR_FMT ", ui32Mapped %d",
+             __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+             psOffsetStruct->uiMMapOffset,
+             psOffsetStruct->ui32Mapped));
+#endif
+}
+
+
+/*
+ * Linux mmap open entry point.
+ */
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+    MMapVOpenNoLock(ps_vma);
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+    PVR_ASSERT(psOffsetStruct != IMG_NULL);
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s: psLinuxMemArea %p, CpuVAddr %p uiMMapOffset " UINTPTR_FMT ", ui32Mapped %d",
+             __FUNCTION__,
+             psOffsetStruct->psLinuxMemArea,
+             LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+             psOffsetStruct->uiMMapOffset,
+             psOffsetStruct->ui32Mapped));
+#endif
+
+    PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+    PVRSRVOffsetStructDecMapped(psOffsetStruct);
+    if (psOffsetStruct->ui32Mapped == 0)
+    {
+	if (psOffsetStruct->ui32RefCount != 0)
+	{
+	        PVR_DPF((
+              PVR_DBG_MESSAGE, 
+              "%s: psOffsetStruct %p has non-zero reference count (ui32RefCount = %u). User mode address of start of mapping: 0x" UINTPTR_FMT, 
+              __FUNCTION__, 
+              psOffsetStruct, 
+              psOffsetStruct->ui32RefCount, 
+              psOffsetStruct->uiUserVAddr));
+	}
+
+	DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    ps_vma->vm_private_data = NULL;
+}
+
+/*
+ * Linux mmap close entry point.
+ */
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+    MMapVCloseNoLock(ps_vma);
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+/*
+ * This vma operation is used to read data from mmap regions. It is called
+ * by access_process_vm, which is called to handle PTRACE_PEEKDATA ptrace
+ * requests and reads from /proc/<pid>/mem.
+ */
+static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
+					   void *buf, int len, int write)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    LinuxMemArea *psLinuxMemArea;
+    unsigned long ulOffset;
+	int iRetVal = -EINVAL;
+	IMG_VOID *pvKernelAddr;
+
+	LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+	psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+	psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+	ulOffset = addr - ps_vma->vm_start;
+
+    if (ulOffset+len > psLinuxMemArea->uiByteSize)
+		/* Out of range. We shouldn't get here, because the kernel will do
+		   the necessary checks before calling access_process_vm. */
+		goto exit_unlock;
+
+	pvKernelAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+	if (pvKernelAddr)
+	{
+		memcpy(buf, pvKernelAddr+ulOffset, len);
+		iRetVal = len;
+	}
+	else
+	{
+		IMG_UINTPTR_T pfn, uiOffsetInPage;
+		struct page *page;
+
+		pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ulOffset);
+
+		if (!pfn_valid(pfn))
+			goto exit_unlock;
+
+		page = pfn_to_page(pfn);
+		uiOffsetInPage = ADDR_TO_PAGE_OFFSET(ulOffset);
+
+		if (uiOffsetInPage + len > PAGE_SIZE)
+			/* The region crosses a page boundary */
+			goto exit_unlock;
+
+		pvKernelAddr = kmap(page);
+		memcpy(buf, pvKernelAddr + uiOffsetInPage, len);
+		kunmap(page);
+
+		iRetVal = len;
+	}
+
+exit_unlock:
+	LinuxUnLockMutex(&g_sMMapMutex);
+    return iRetVal;
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) */
+
+static struct vm_operations_struct MMapIOOps =
+{
+	.open=MMapVOpen,
+	.close=MMapVClose,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+	.access=MMapVAccess,
+#endif
+};
+
+
+/*!
+ *******************************************************************************
+
+ @Function  PVRMMap
+
+ @Description
+
+ Driver mmap entry point.
+
+ @input pFile : unused.
+ @input ps_vma : pointer to linux memory area descriptor.
+
+ @Return 0, or Linux error code.
+
+ ******************************************************************************/
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+    LinuxMemArea *psFlushMemArea = IMG_NULL;
+    PKV_OFFSET_STRUCT psOffsetStruct;
+    IMG_SIZE_T uiByteSize;
+    IMG_VOID *pvBase = IMG_NULL;
+    int iRetVal = 0;
+    IMG_UINTPTR_T uiByteOffset = 0;	/* Keep compiler happy */
+    IMG_SIZE_T uiFlushSize = 0;
+
+    PVR_UNREFERENCED_PARAMETER(pFile);
+
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+    
+    uiByteSize = ps_vma->vm_end - ps_vma->vm_start;
+    
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x" UINTPTR_FMT ","
+                              " and uiByteSize %" SIZE_T_FMT_LEN "u(0x%" SIZE_T_FMT_LEN "x)",
+            __FUNCTION__,
+            ps_vma->vm_pgoff,
+            uiByteSize, 
+            uiByteSize));
+   
+    psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, uiByteSize);
+
+    if (psOffsetStruct == IMG_NULL)
+    {
+#if defined(SUPPORT_DRI_DRM)
+		LinuxUnLockMutex(&g_sMMapMutex);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+		/* Pass unknown requests onto the DRM module */
+		return drm_mmap(pFile, ps_vma);
+#else
+        /*
+         * Indicate to caller that the request is not for us.
+         * Do not return this error elsewhere in this function, as the
+         * caller may use it as a clue as to whether the mmap request
+         * should be passed on to another component (e.g. drm_mmap).
+         */
+        return -ENOENT;
+#endif
+#else
+        PVR_UNREFERENCED_PARAMETER(pFile);
+
+        PVR_DPF((PVR_DBG_ERROR,
+             "%s: Attempted to mmap unregistered area at vm_pgoff 0x%lx",
+             __FUNCTION__, ps_vma->vm_pgoff));
+        iRetVal = -EINVAL;
+#endif
+        goto unlock_and_return;
+    }
+
+    list_del(&psOffsetStruct->sMMapItem);
+    psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+    /* Only support shared writeable mappings */
+    if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+        ((ps_vma->vm_flags & VM_SHARED) == 0))
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+        iRetVal = -EINVAL;
+        goto unlock_and_return;
+    }
+   
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+         __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0))
+    /* This is probably superfluous and implied by VM_IO */
+    ps_vma->vm_flags |= VM_RESERVED;
+#else
+    ps_vma->vm_flags |= VM_DONTDUMP;
+#endif
+    ps_vma->vm_flags |= VM_IO;
+
+    /*
+     * Disable mremap because our nopage handler assumes all
+     * page requests have already been validated.
+     */
+    ps_vma->vm_flags |= VM_DONTEXPAND;
+    
+    /* Don't allow mapping to be inherited across a process fork */
+    ps_vma->vm_flags |= VM_DONTCOPY;
+
+    ps_vma->vm_private_data = (void *)psOffsetStruct;
+    
+    switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+    {
+        case PVRSRV_HAP_CACHED:
+            /* This is the default, do nothing. */
+            break;
+        case PVRSRV_HAP_WRITECOMBINE:
+            ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+            break;
+        case PVRSRV_HAP_UNCACHED:
+            ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+            iRetVal = -EINVAL;
+	    goto unlock_and_return;
+    }
+
+#ifdef CONFIG_ARCH_OMAP5
+    {
+	IMG_BOOL bModPageProt = IMG_FALSE;
+
+#ifdef CONFIG_DSSCOMP
+	bModPageProt |= is_tiler_addr(LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0).uiAddr);
+#endif /* CONFIG_DSSCOMP */ 
+
+	if (bModPageProt)
+	{
+		ps_vma->vm_page_prot = __pgprot_modify(ps_vma->vm_page_prot,
+					       L_PTE_MT_MASK,
+					       L_PTE_MT_DEV_SHARED);
+	}
+    }
+#endif /* CONFIG_ARCH_OMAP5 */
+
+    /* Install open and close handlers for ref-counting */
+    ps_vma->vm_ops = &MMapIOOps;
+    
+    if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+    {
+        iRetVal = -EAGAIN;
+        goto unlock_and_return;
+    }
+    
+    PVR_ASSERT(psOffsetStruct->uiUserVAddr == 0);
+
+    psOffsetStruct->uiUserVAddr = ps_vma->vm_start;
+
+    /* Compute the flush region (if necessary) inside the mmap mutex */
+    if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
+    {
+        psFlushMemArea = psOffsetStruct->psLinuxMemArea;
+
+		/* Sparse mappings have to ask the BM for the virtual size */
+		if (psFlushMemArea->hBMHandle)
+		{
+			pvBase = (IMG_VOID *)ps_vma->vm_start;
+			uiByteOffset = 0;
+			uiFlushSize = BM_GetVirtualSize(psFlushMemArea->hBMHandle);
+		}
+		else
+		{
+			IMG_SIZE_T uiDummyByteSize;
+
+	        DetermineUsersSizeAndByteOffset(psFlushMemArea,
+	                                        &uiDummyByteSize,
+	                                        &uiByteOffset);
+	
+	        pvBase = (IMG_VOID *)ps_vma->vm_start + uiByteOffset;
+	        uiFlushSize = psFlushMemArea->uiByteSize;
+		}
+
+        psFlushMemArea->bNeedsCacheInvalidate = IMG_FALSE;
+    }
+
+    /* Call the open routine to increment the usage count */
+    MMapVOpenNoLock(ps_vma);
+
+    PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x" UINTPTR_FMT "\n",
+             __FUNCTION__, (IMG_UINTPTR_T)ps_vma->vm_pgoff));
+
+unlock_and_return:
+    if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+    {
+        DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+
+    if(psFlushMemArea && uiFlushSize)
+    {
+        OSInvalidateCPUCacheRangeKM(psFlushMemArea, uiByteOffset, pvBase,
+									uiFlushSize);
+    }
+
+    return iRetVal;
+}
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+/*
+ * Lock MMap regions list (called on page start/stop while reading /proc/mmap)
+
+ * sfile : seq_file that handles /proc file
+ * start : TRUE if it's start, FALSE if it's stop
+ *  
+*/
+static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start) 
+{
+	if(start) 
+	{
+	    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);		
+	}
+	else
+	{
+	    LinuxUnLockMutex(&g_sMMapMutex);
+	}
+}
+
+
+/*
+ * Convert offset (index from KVOffsetTable) to element 
+ * (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * off : index into the KVOffsetTable from which to print
+ *  
+ * returns void* : Pointer to element that will be dumped
+ *  
+*/
+static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
+{
+    LinuxMemArea *psLinuxMemArea;
+	if(!off) 
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+    list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+    {
+        PKV_OFFSET_STRUCT psOffsetStruct;
+
+	 	list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+        {
+	    	off--;
+	    	if (off == 0)
+	    	{				
+				PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+				return (void*)psOffsetStruct;
+		    }
+        }
+    }
+	return (void*)0;
+}
+
+/*
+ * Gets next MMap element to show. (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ * off : index into the KVOffsetTable from which to print
+ *  
+ * returns void* : Pointer to element to show (0 ends iteration)
+*/
+static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
+{
+	return ProcSeqOff2ElementMMapRegistrations(sfile,off);
+}
+
+/*
+ * Show MMap element (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ *  
+*/
+static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
+{
+	KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
+    LinuxMemArea *psLinuxMemArea;
+	IMG_SIZE_T uiRealByteSize;
+	IMG_UINTPTR_T uiByteOffset;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN) 
+	{
+        seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+						  "Allocations registered for mmap: %u\n"
+                          "In total these areas correspond to %" SIZE_T_FMT_LEN "u bytes\n"
+                          "psLinuxMemArea "
+						  "UserVAddr "
+						  "KernelVAddr "
+						  "CpuPAddr "
+                          "MMapOffset "
+                          "ByteLength "
+                          "LinuxMemType             "
+						  "Pid   Name     Flags\n",
+#else
+                          "<mmap_header>\n"
+                          "\t<count>%u</count>\n"
+                          "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
+                          "</mmap_header>\n",
+#endif
+						  g_ui32RegisteredAreas,
+                          g_uiTotalByteSize
+                          );
+		return;
+	}
+
+   	psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+
+	DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+									&uiRealByteSize,
+									&uiByteOffset);
+
+	seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+						"%p       %p %p " CPUPADDR_FMT " " UINTPTR_FMT "   %" SIZE_T_FMT_LEN "u   %-24s %-5u %-8s %08x(%s)\n",
+#else
+                        "<mmap_record>\n"
+						"\t<pointer>%p</pointer>\n"
+                        "\t<user_virtual>%p</user_virtual>\n"
+                        "\t<kernel_virtual>%p</kernel_virtual>\n"
+                        "\t<cpu_physical>" CPUPADDR_FMT "</cpu_physical>\n"
+                        "\t<mmap_offset>" UINTPTR_FMT "</mmap_offset>\n"
+                        "\t<bytes>%" SIZE_T_FMT_LEN "u</bytes>\n"
+                        "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+                        "\t<pid>%-5u</pid>\n"
+                        "\t<name>%-8s</name>\n"
+                        "\t<flags>%08x</flags>\n"
+                        "\t<flags_string>%s</flags_string>\n"
+                        "</mmap_record>\n",
+#endif
+                        psLinuxMemArea,
+						(IMG_PVOID)(psOffsetStruct->uiUserVAddr + uiByteOffset),
+						LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+                        LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+						(IMG_UINTPTR_T)psOffsetStruct->uiMMapOffset,
+						psLinuxMemArea->uiByteSize,
+                        LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+						psOffsetStruct->ui32PID,
+						psOffsetStruct->pszName,
+						psLinuxMemArea->ui32AreaFlags,
+                        HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+}
+
+#endif
+
+
+/*!
+ *******************************************************************************
+
+ @Function  PVRMMapRegisterArea
+
+ @Description
+
+ Register a memory area with the mmap code.
+
+ @input psLinuxMemArea : pointer to memory area.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+    PVR_DPF((PVR_DBG_MESSAGE,
+             "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8x)",
+             __FUNCTION__, pszName, psLinuxMemArea,  psLinuxMemArea->ui32AreaFlags));
+#endif
+
+    PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+    /* Check this mem area hasn't already been registered */
+    if(psLinuxMemArea->bMMapRegistered)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+                __FUNCTION__, psLinuxMemArea));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+	goto exit_unlock;
+    }
+
+    list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+    psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    g_ui32RegisteredAreas++;
+    /*
+     * Sub memory areas are excluded from g_ui32TotalByteSize so that we
+     * don't count memory twice, once for the parent and again for sub
+     * allocationis.
+     */
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_uiTotalByteSize += psLinuxMemArea->uiByteSize;
+    }
+#endif
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+
+    return eError;
+}
+
+
+/*!
+ *******************************************************************************
+
+ @Function  PVRMMapRemoveRegisterArea
+
+ @Description
+
+ Unregister a memory area with the mmap code.
+
+ @input psLinuxMemArea : pointer to memory area.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+    PVRSRV_ERROR eError;
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+    PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+    {
+	if (psOffsetStruct->ui32Mapped != 0)
+	{
+	     PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u",  __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+		dump_stack();
+		PVRSRVDumpRefCountCCB();
+		eError = PVRSRV_ERROR_STILL_MAPPED;
+		goto exit_unlock;
+	}
+	else
+	{
+	      /*
+	      * An offset structure is created when a call is made to get
+	      * the mmap data for a physical mapping.  If the data is never
+	      * used for mmap, we will be left with an umapped offset
+	      * structure.
+	      */
+	     PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped",  __FUNCTION__, psOffsetStruct));
+	}
+
+	PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+	DestroyOffsetStruct(psOffsetStruct);
+    }
+
+    list_del(&psLinuxMemArea->sMMapItem);
+
+    psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    g_ui32RegisteredAreas--;
+    if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+    {
+        g_uiTotalByteSize -= psLinuxMemArea->uiByteSize;
+    }
+#endif
+
+    eError = PVRSRV_OK;
+
+exit_unlock:
+    LinuxUnLockMutex(&g_sMMapMutex);
+    return eError;
+}
+
+
+/*!
+ *******************************************************************************
+
+ @Function  LinuxMMapPerProcessConnect
+
+ @Description
+
+ Per-process mmap initialisation code.
+
+ @input psEnvPerProc : pointer to OS specific per-process data.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    return PVRSRV_OK;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function  LinuxMMapPerProcessDisconnect
+
+ @Description
+
+ Per-process mmap deinitialisation code.
+
+ @input psEnvPerProc : pointer to OS specific per-process data.
+
+ ******************************************************************************/
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+    PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+    IMG_BOOL bWarn = IMG_FALSE;
+    IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+    PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+    LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+    list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+    {
+	if (psOffsetStruct->ui32PID == ui32PID)
+	{
+	    if (!bWarn)
+	    {
+		PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+		bWarn = IMG_TRUE;
+	    }
+	    PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+	    PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+	    DestroyOffsetStruct(psOffsetStruct);
+	}
+    }
+
+    LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+/*!
+ *******************************************************************************
+
+ @Function  LinuxMMapPerProcessHandleOptions
+
+ @Description
+
+ Set secure handle options required by mmap code.
+
+ @input psHandleBase : pointer to handle base.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+    PVRSRV_ERROR eError;
+
+    eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+    if (eError != PVRSRV_OK)
+    {
+	PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+	return eError;
+    }
+
+    return eError;
+}
+
+
+/*!
+ *******************************************************************************
+
+ @Function  PVRMMapInit
+
+ @Description
+
+ MMap initialisation code
+
+ ******************************************************************************/
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+    LinuxInitMutex(&g_sMMapMutex);
+
+    g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
+    if (!g_psMemmapCache)
+    {
+        PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+	goto error;
+    }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+	g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL, 
+						  ProcSeqNextMMapRegistrations,
+						  ProcSeqShowMMapRegistrations,
+						  ProcSeqOff2ElementMMapRegistrations,
+						  ProcSeqStartstopMMapRegistations
+						 );
+#endif  /* defined(DEBUG_LINUX_MMAP_AREAS) */
+    return;
+
+error:
+    PVRMMapCleanup();
+    return;
+}
+
+
+/*!
+ *******************************************************************************
+
+ @Function  PVRMMapCleanup
+
+ @Description
+
+ Mmap deinitialisation code
+
+ ******************************************************************************/
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+    PVRSRV_ERROR eError;
+
+    if (!list_empty(&g_sMMapAreaList))
+    {
+	LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+	PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+	
+	PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+ 	list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+	{
+		eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+		}
+		PVR_ASSERT(eError == PVRSRV_OK);
+
+		LinuxMemAreaDeepFree(psLinuxMemArea);
+	}
+    }
+    PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    RemoveProcEntrySeq(g_ProcMMap);
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
+
+    if(g_psMemmapCache)
+    {
+        KMemCacheDestroyWrapper(g_psMemmapCache);
+        g_psMemmapCache = NULL;
+    }
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h
new file mode 100644
index 0000000..72640e3
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mmap.h
@@ -0,0 +1,232 @@
+/*************************************************************************/ /*!
+@Title          Linux mmap interface declaration
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#if defined(VM_MIXEDMAP)
+/*
+ * Mixed maps allow us to avoid using raw PFN mappings (VM_PFNMAP) for
+ * pages without pages structures ("struct page"), giving us more
+ * freedom in choosing the mmap offset for mappings.  Mixed maps also
+ * allow both the mmap and the wrap code to be simplified somewhat.
+ */
+#define	PVR_MAKE_ALL_PFNS_SPECIAL
+#endif
+
+#include "perproc.h"
+#include "mm.h"
+
+/*
+ * This structure represents the relationship between an mmap2 file
+ * offset and a LinuxMemArea for a given process.
+ */
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+    /*
+     * Mapping count.  Incremented when the mapping is created, and
+     * if the mapping is inherited across a process fork.
+     */
+    IMG_UINT32			ui32Mapped;
+
+    /*
+     * Offset to be passed to mmap2 to map the associated memory area
+     * into user space.  The offset may represent the page frame number
+     * of the first page in the area (if the area is physically
+     * contiguous), or it may represent the secure handle associated
+     * with the area.
+     */
+    IMG_UINTPTR_T       uiMMapOffset;
+
+    IMG_SIZE_T			uiRealByteSize;
+
+    /* Memory area associated with this offset structure */
+    LinuxMemArea                *psLinuxMemArea;
+    
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+    /* ID of the thread that owns this structure */
+    IMG_UINT32			ui32TID;
+#endif
+
+    /* ID of the process that owns this structure */
+    IMG_UINT32			ui32PID;
+
+    /*
+     * For offsets that represent actual page frame numbers, this structure
+     * is temporarily put on a list so that it can be found from the
+     * driver mmap entry point.  This flag indicates the structure is
+     * on the list.
+     */
+    IMG_BOOL			bOnMMapList;
+
+    /* Reference count for this structure */
+    IMG_UINT32			ui32RefCount;
+
+    /*
+     * User mode address of start of mapping.  This is not necessarily the
+     * first user mode address of the memory area.
+     */
+    IMG_UINTPTR_T		uiUserVAddr;
+
+    /* Extra entries to support proc filesystem debug info */
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+    const IMG_CHAR		*pszName;
+#endif
+    
+   /* List entry field for MMap list */
+   struct list_head		sMMapItem;
+
+   /* List entry field for per-memory area list */
+   struct list_head		sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+/*!
+ *******************************************************************************
+ * @Function Mmap initialisation code
+ ******************************************************************************/
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+/*!
+ *******************************************************************************
+ * @Function Mmap de-initialisation code
+ ******************************************************************************/
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+/*!
+ *******************************************************************************
+ * @Function Registers a memory area with the mmap code
+ *          
+ * @Input psLinuxMemArea
+ *
+ * @Return PVRSRV_ERROR status
+ ******************************************************************************/
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ *******************************************************************************
+ * @Function Unregisters a memory area from the mmap code
+ *
+ * @Input psLinuxMemArea
+ *
+ * @Return PVRSRV_ERROR status
+ ******************************************************************************/
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+/*!
+ ******************************************************************************
+ * @Function When a userspace services client, requests to map a memory
+ *           area to userspace, this function validates the request and
+ *           returns the details that the client must use when calling mmap(2).
+ *
+ * @Input psPerProc		Per process data.
+ * @Input hMHandle              Handle associated with the memory to map.
+ *				This is a (secure) handle to the OS specific
+ *				memory handle structure (hOSMemHandle), or
+ *				a handle to a structure that contains the 
+ *				memory handle.
+ * @Output pui32MMapOffset      The page aligned offset that the client must
+ *				pass to the mmap2 system call.
+ * @Output pui32ByteOffset       The real mapping that will be created for the
+ *				services client may have a different
+ *				size/alignment from it request. This offset
+ *				is returned to the client and should be added
+ *				to virtual address returned from mmap2 to get
+ *				the first address corresponding to its request.
+ * @Output pui32RealByteOffset   The size that the mapping will really be,
+ *				that the client must also pass to mmap/munmap.
+ *
+ * @Output pui32UserVAddr	Pointer to returned user mode address of 
+ * 				mapping.
+ * @Return PVRSRV_ERROR
+ ******************************************************************************/
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+                                          IMG_HANDLE hMHandle,
+                                          IMG_UINTPTR_T *puiMMapOffset,
+                                          IMG_UINTPTR_T *puiByteOffset,
+                                          IMG_SIZE_T *puiRealByteSize,
+                                          IMG_UINTPTR_T *puiUserVAddr);
+
+/*!
+ *******************************************************************************
+
+ @Function Release mmap data.
+
+ @Input psPerProc            Per-process data.
+ @Input hMHandle             Memory handle.
+
+ @Output pbMUnmap            Flag that indicates whether an munmap is
+		             required.
+ @Output pui32RealByteSize   Location for size of mapping.
+ @Output pui32UserVAddr      User mode address to munmap.
+
+ @Return PVRSRV_ERROR
+ ******************************************************************************/
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+				IMG_HANDLE hMHandle,
+				IMG_BOOL *pbMUnmap,
+				IMG_SIZE_T *puiRealByteSize,
+                IMG_UINTPTR_T *puiUserVAddr);
+
+/*!
+ *******************************************************************************
+ * @Function driver mmap entry point
+ * 
+ * @Input pFile : user file structure
+ *
+ * @Input ps_vma : vm area structure
+ * 
+ * @Return 0 for success, -errno for failure.
+ ******************************************************************************/
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif	/* __MMAP_H__ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/module.c b/drivers/gpu/pvr/services4/srvkm/env/linux/module.c
new file mode 100644
index 0000000..fafd089
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/module.c
@@ -0,0 +1,1288 @@
+/*************************************************************************/ /*!
+@Title          Linux module setup
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#define	PVR_MOD_STATIC
+#else
+	/*
+	 * For LDM drivers, define PVR_LDM_MODULE to indicate generic LDM
+	 * support is required, besides indicating the exact support
+	 * required (e.g. platform, or PCI device).
+	 */
+	#if defined(LDM_PLATFORM)
+		#define	PVR_LDM_PLATFORM_MODULE
+		#define PVR_LDM_DEVICE_CLASS
+		#define	PVR_LDM_MODULE
+	#else
+		#if defined(LDM_PCI)
+			#define PVR_LDM_DEVICE_CLASS
+			#define PVR_LDM_PCI_MODULE
+			#define	PVR_LDM_MODULE
+		#else
+			#if defined(SYS_SHARES_WITH_3PKM)
+				#define PVR_LDM_DEVICE_CLASS
+			#endif
+		#endif
+	#endif
+#define	PVR_MOD_STATIC	static
+#endif
+
+#if (defined(PVR_LDM_PLATFORM_PRE_REGISTERED) || defined(PVR_LDM_DEVICE_TREE)) && !defined(NO_HARDWARE)
+#define PVR_USE_PRE_REGISTERED_PLATFORM_DEV
+#endif
+
+#if defined(PVR_LDM_DEVICE_TREE) && !defined(NO_HARDWARE)
+#define PVR_USE_DEVICE_TREE
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#include <linux/platform_device.h>
+#endif /* PVR_LDM_PLATFORM_MODULE */
+
+#if defined(PVR_LDM_PCI_MODULE)
+#include <linux/pci.h>
+#endif /* PVR_LDM_PCI_MODULE */
+
+#if defined(PVR_LDM_DEVICE_CLASS)
+#include <linux/device.h>
+#endif /* PVR_LDM_DEVICE_CLASS */
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+#include <asm/uaccess.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "lock.h"
+#include "linkage.h"
+#include "buffer_manager.h"
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include "pvr_sync_common.h"
+#endif
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+#include "systrace.h"
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if defined(SUPPORT_DMABUF)
+#include "pvr_linux_fence.h"
+#endif
+
+/*
+ * DRVNAME is the name we use to register our driver.
+ * DEVNAME is the name we use to register actual device nodes.
+ */
+#if defined(PVR_LDM_MODULE)
+#define	DRVNAME		PVR_LDM_DRIVER_REGISTRATION_NAME
+#endif
+#define DEVNAME		PVRSRV_MODNAME
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+/*
+ * This is all module configuration stuff required by the linux kernel.
+ */
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+#include <linux/moduleparam.h>
+extern IMG_UINT32 gPVRDebugLevel;
+module_param(gPVRDebugLevel, uint, 0644);
+MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+#if !defined(__devinitdata)
+#define __devinitdata
+#endif
+#if !defined(__devinit)
+#define __devinit
+#endif
+#if !defined(__devexit)
+#define __devexit
+#endif
+#if !defined(__devexit_p)
+#define __devexit_p(x) (&(x))
+#endif
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+/* PRQA S 3207 2 */ /* ignore 'not used' warning */
+EXPORT_SYMBOL(PVRGetDisplayClassJTable);
+EXPORT_SYMBOL(PVRGetBufferClassJTable);
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+#if defined(PVR_LDM_DEVICE_CLASS) && !defined(SUPPORT_DRI_DRM)
+/*
+ * Device class used for /sys entries (and udev device node creation)
+ */
+static struct class *psPvrClass;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+/*
+ * This is the major number we use for all nodes in /dev.
+ */
+static int AssignedMajorNumber;
+
+/*
+ * These are the operations that will be associated with the device node
+ * we create.
+ *
+ * With gcc -W, specifying only the non-null members produces "missing
+ * initializer" warnings.
+*/
+static int PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static int PVRSRVRelease(struct inode* pInode, struct file* pFile);
+
+static struct file_operations pvrsrv_fops =
+{
+	.owner=THIS_MODULE,
+	.unlocked_ioctl = PVRSRV_BridgeDispatchKM,
+#if defined(CONFIG_COMPAT)
+	.compat_ioctl	= PVRSRV_BridgeCompatDispatchKM,
+#endif
+	.open=PVRSRVOpen,
+	.release=PVRSRVRelease,
+	.mmap=PVRMMap,
+};
+#endif
+
+PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+/* PID of process being released */
+IMG_UINT32 gui32ReleasePID;
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+static IMG_UINT32 gPVRPowerLevel;
+#endif
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+#define	LDM_DEV	struct platform_device
+#define	LDM_DRV	struct platform_driver
+#endif /*PVR_LDM_PLATFORM_MODULE */
+
+#if defined(PVR_LDM_PCI_MODULE)
+#define	LDM_DEV	struct pci_dev
+#define	LDM_DRV	struct pci_driver
+#endif /* PVR_LDM_PCI_MODULE */
+/*
+ * This is the driver interface we support.  
+ */
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static void PVRSRVDriverRemove(LDM_DEV *device);
+static int PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+static int PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
+static void PVRSRVDriverShutdown(LDM_DEV *device);
+static int PVRSRVDriverResume(LDM_DEV *device);
+
+#if defined(PVR_LDM_PCI_MODULE)
+/* This structure is used by the Linux module code */
+struct pci_device_id powervr_id_table[] __devinitdata = {
+	{PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID)},
+#if defined (SYS_SGX_DEV1_DEVICE_ID)
+	{PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID)},
+#endif
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif
+
+#if defined(PVR_USE_DEVICE_TREE)
+static struct of_device_id powervr_id_table[] = {
+	{
+		.compatible = SYS_SGX_DEV_NAME
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, powervr_id_table);
+#else
+#if defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+static struct platform_device_id powervr_id_table[] __devinitdata = {
+	{SYS_SGX_DEV_NAME, 0},
+	{}
+};
+#endif
+#endif
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+	.driver = {
+		.name		= DRVNAME,
+#if defined(PVR_USE_DEVICE_TREE)
+		.of_match_table = powervr_id_table,
+#endif
+	},
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+	.name		= DRVNAME,
+#endif
+#if (defined(PVR_LDM_PCI_MODULE) || defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)) && !defined(PVR_USE_DEVICE_TREE)
+	.id_table = powervr_id_table,
+#endif
+	.probe		= PVRSRVDriverProbe,
+#if defined(PVR_LDM_PLATFORM_MODULE)
+	.remove		= PVRSRVDriverRemove,
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+	.remove		= __devexit_p(PVRSRVDriverRemove),
+#endif
+	.suspend	= PVRSRVDriverSuspend,
+	.resume		= PVRSRVDriverResume,
+	.shutdown	= PVRSRVDriverShutdown,
+};
+
+LDM_DEV *gpsPVRLDMDev;
+
+#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE) && \
+	!defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+static void PVRSRVDeviceRelease(struct device unref__ *pDevice)
+{
+}
+
+static struct platform_device powervr_device = {
+	.name			= DEVNAME,
+	.id				= -1,
+	.dev 			= {
+		.release	= PVRSRVDeviceRelease
+	}
+};
+#endif
+
+/*!
+******************************************************************************
+
+ @Function		PVRSRVDriverProbe
+
+ @Description
+
+ See whether a given device is really one we can drive.  The platform bus
+ handler has already established that we should be able to service this device
+ because of the name match.  We probably don't need to do anything else.
+
+ @input pDevice - the device for which a probe is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id)
+#endif
+{
+	SYS_DATA *psSysData;
+
+	PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
+
+#if 0   /* INTEGRATION_POINT */
+	/* Some systems require device-specific system initialisation.
+	 * E.g. this lets the OS track a device's dependencies on various
+	 * system hardware.
+	 *
+	 * Note: some systems use this to enable HW that SysAcquireData
+	 * will depend on, therefore it must be called first.
+	 */
+	if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+	{
+		return -EINVAL;
+	}
+#endif	
+	/* SysInitialise only designed to be called once.
+	 */
+	psSysData = SysAcquireDataNoCheck();
+	if (psSysData == IMG_NULL)
+	{
+		gpsPVRLDMDev = pDevice;
+		if (SysInitialise() != PVRSRV_OK)
+		{
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		PVRSRVDriverRemove
+
+ @Description
+
+ This call is the opposite of the probe call: it is called when the device is
+ being removed from the driver's control.  See the file $KERNELDIR/drivers/
+ base/bus.c:device_release_driver() for the call to this function.
+
+ This is the correct place to clean up anything our driver did while it was
+ asoociated with the device.
+
+ @input pDevice - the device for which driver detachment is happening
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined (PVR_LDM_PLATFORM_MODULE)
+static int PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+	SYS_DATA *psSysData;
+
+	PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+
+	SysAcquireData(&psSysData);
+	
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+	if (gPVRPowerLevel != 0)
+	{
+		if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+		{
+			gPVRPowerLevel = 0;
+		}
+	}
+#endif
+	(void) SysDeinitialise(psSysData);
+
+	gpsPVRLDMDev = IMG_NULL;
+
+#if 0   /* INTEGRATION_POINT */
+	/* See previous integration point for details. */
+	if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
+	{
+		return -EINVAL;
+	}
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+	return 0;
+#endif
+#if defined (PVR_LDM_PCI_MODULE)
+	return;
+#endif
+}
+#endif /* defined(PVR_LDM_MODULE) */
+
+#if !defined(SUPPORT_DRI_DRM)
+struct device *PVRLDMGetDevice(void)
+{
+#if defined(PVR_LDM_MODULE)
+	return &gpsPVRLDMDev->dev;
+#else
+	return NULL;
+#endif
+}
+#endif
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+static PVRSRV_LINUX_MUTEX gsPMMutex;
+static IMG_BOOL bDriverIsSuspended;
+static IMG_BOOL bDriverIsShutdown;
+#endif
+
+#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV)
+/*!
+******************************************************************************
+
+ @Function		PVRSRVDriverShutdown
+
+ @Description
+
+ Suspend device operation for system shutdown.  This is called as part of the
+ system halt/reboot process.  The driver is put into a quiescent state by 
+ setting the power state to D3.
+
+ @input pDevice - the device for which shutdown is requested
+
+ @Return nothing
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+	!defined(SUPPORT_DRI_DRM_PLUGIN)
+void PVRSRVDriverShutdown(struct drm_device *pDevice)
+#else
+PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice)
+#endif
+{
+	PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+	LinuxLockMutexNested(&gsPMMutex, PVRSRV_LOCK_CLASS_POWER);
+
+	if (!bDriverIsShutdown && !bDriverIsSuspended)
+	{
+#if defined(ANDROID)
+		/*
+		 * Take the bridge mutex, and never release it, to stop
+		 * processes trying to use the driver after it has been
+		 * shutdown.
+		 */
+		LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+#endif
+		(void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+	}
+
+	bDriverIsShutdown = IMG_TRUE;
+
+	/* The bridge mutex is held on exit */
+	LinuxUnLockMutex(&gsPMMutex);
+}
+
+#endif /* defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV) */
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+/*!
+******************************************************************************
+
+ @Function		PVRSRVDriverSuspend
+
+ @Description
+
+ For 2.6 kernels:
+ Suspend device operation.  We always get three calls to this regardless of
+ the state (D1-D3) chosen.  The order is SUSPEND_DISABLE, SUSPEND_SAVE_STATE
+ then SUSPEND_POWER_DOWN.  We take action as soon as we get the disable call,
+ the other states not being handled by us yet.
+
+ For MontaVista 2.4 kernels:
+ This call gets made once only when someone does something like
+
+	# echo -e -n "suspend powerdown 0" >/sys.devices/legacy/pvrsrv0/power
+
+ The 3rd, numeric parameter (0) in the above has no relevence and is not
+ passed into us.  The state parameter is always zero and the level parameter
+ is always SUSPEND_POWER_DOWN.  Vive la difference!
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+	!defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverSuspend(struct pci_dev *pDevice, pm_message_t state)
+#else
+int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#endif
+#else
+PVR_MOD_STATIC int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
+#endif
+{
+	int res = 0;
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+	PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
+
+	LinuxLockMutexNested(&gsPMMutex, PVRSRV_LOCK_CLASS_POWER);
+
+	if (!bDriverIsSuspended && !bDriverIsShutdown)
+	{
+#if defined(ANDROID)
+		/*
+		 * The bridge mutex will be held until we resume.
+		 * The lock doesn't need to be taken on (non-Android)
+		 * Linux systems, as all user processes will have been
+		 * suspended at this point. In any case, taking the mutex
+		 * may result in possible lock ordering problems being
+		 * flagged up by the kernel, as the Linux console lock may
+		 * have already been taken at this point. If the 3rd party
+		 * display driver is Linux Framebuffer based, the previous
+		 * locking order may have been bridge mutex first, followed
+		 * by the console lock.
+		 */
+		LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+#endif
+		if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) == PVRSRV_OK)
+		{
+			bDriverIsSuspended = IMG_TRUE;
+		}
+		else
+		{
+#if defined(ANDROID)
+			LinuxUnLockMutex(&gPVRSRVLock);
+#endif
+			res = -EINVAL;
+		}
+	}
+
+	LinuxUnLockMutex(&gsPMMutex);
+#endif
+	return res;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		PVRSRVDriverResume
+
+ @Description
+
+ Resume device operation following a lull due to earlier suspension.  It is
+ implicit we're returning to D0 (fully operational) state.  We always get three
+ calls to this using level thus: RESUME_POWER_ON, RESUME_RESTORE_STATE then
+ RESUME_ENABLE.  On 2.6 kernels We don't do anything until we get the enable
+ call; on the MontaVista set-up we only ever get the RESUME_POWER_ON call.
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
+	!defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverResume(struct pci_dev *pDevice)
+#else
+int PVRSRVDriverResume(struct drm_device *pDevice)
+#endif
+#else
+PVR_MOD_STATIC int PVRSRVDriverResume(LDM_DEV *pDevice)
+#endif
+{
+	int res = 0;
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+	PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+
+	LinuxLockMutexNested(&gsPMMutex, PVRSRV_LOCK_CLASS_POWER);
+
+	if (bDriverIsSuspended && !bDriverIsShutdown)
+	{
+		if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+		{
+			bDriverIsSuspended = IMG_FALSE;
+#if defined(ANDROID)
+			LinuxUnLockMutex(&gPVRSRVLock);
+#endif
+		}
+		else
+		{
+#if defined(ANDROID)
+			/* The bridge mutex is not released on failure */
+#endif
+			res = -EINVAL;
+		}
+	}
+
+	LinuxUnLockMutex(&gsPMMutex);
+#endif
+	return res;
+}
+#endif /* defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM) */
+
+
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+/*
+ * If PVR_LDM_PCI_MODULE is defined (and PVR_MANUAL_POWER_CONTROL is *NOT* defined),
+ * the device can be suspended and resumed without suspending/resuming the
+ * system, by writing values into the power/state sysfs file for the device.
+ * To suspend:
+ *	echo -n 2 > power/state
+ * To Resume:
+ *	echo -n 0 > power/state
+ *
+ * The problem with this approach is that the device is usually left
+ * powered up; it is the responsibility of the bus driver to remove
+ * the power.
+ *
+ * Defining PVR_MANUAL_POWER_CONTROL is intended to make it easier to
+ * debug power management issues, especially when power is really removed
+ * from the device.  It is easier to debug the driver if it is not being
+ * suspended/resumed with the rest of the system.
+ *
+ * When PVR_MANUAL_POWER_CONTROL is defined, the following proc entry is
+ * created:
+ * 	/proc/pvr/power_control
+ * The driver suspend/resume entry points defined below no longer suspend or
+ * resume the device.  To suspend the device, type the following:
+ * 	echo 2 > /proc/pvr/power_control
+ * To resume the device, type:
+ * 	echo 0 > /proc/pvr/power_control
+ * 
+ * The following example shows how to suspend/resume the device independently
+ * of the rest of the system.
+ * Suspend the device:
+ * 	echo 2 > /proc/pvr/power_control
+ * Suspend the system.  Then you should be able to suspend and resume
+ * as normal.  To resume the device type the following:
+ * 	echo 0 > /proc/pvr/power_control
+ */
+
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+	IMG_CHAR data_buffer[2];
+	IMG_UINT32 PVRPowerLevel;
+
+	if (count != sizeof(data_buffer))
+	{
+		return -EINVAL;
+	}
+	else
+	{
+		if (copy_from_user(data_buffer, buffer, count))
+			return -EINVAL;
+		if (data_buffer[count - 1] != '\n')
+			return -EINVAL;
+		PVRPowerLevel = data_buffer[0] - '0';
+		if (PVRPowerLevel != gPVRPowerLevel)
+		{
+			if (PVRPowerLevel != 0)
+			{
+				if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+				{
+					return -EINVAL;
+				}
+			}
+			else
+			{
+				if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+				{
+					return -EINVAL;
+				}
+			}
+
+			gPVRPowerLevel = PVRPowerLevel;
+		}
+	}
+	return (count);
+}
+
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)	
+{
+	seq_printf(sfile, "%lu\n", gPVRPowerLevel);
+}
+
+#endif
+
+/*!
+******************************************************************************
+
+ @Function		PVRSRVOpen
+
+ @Description
+
+ Open the PVR services node - called when the relevant device node is open()ed.
+
+ @input pInode - the inode for the file being openeded
+ @input dev    - the DRM device corresponding to this driver.
+
+ @input pFile - the file handle data for the actual file being opened
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM)
+int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+	PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+	IMG_HANDLE hBlockAlloc;
+	int iRet = -ENOMEM;
+	PVRSRV_ERROR eError;
+	IMG_UINT32 ui32PID;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+#endif
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	ui32PID = OSGetCurrentProcessIDKM();
+
+	if (PVRSRVProcessConnect(ui32PID, 0) != PVRSRV_OK)
+		goto err_unlock;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+	if (psEnvPerProc == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__));
+		goto err_unlock;
+	}
+#endif
+
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+						sizeof(PVRSRV_FILE_PRIVATE_DATA),
+						(IMG_PVOID *)&psPrivateData,
+						&hBlockAlloc,
+						"File Private Data");
+
+	if(eError != PVRSRV_OK)
+		goto err_unlock;
+
+	psPrivateData->hKernelMemInfo = NULL;
+	pFile->f_mode |= FMODE_UNSIGNED_OFFSET;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	psPrivateData->psDRMFile = pFile;
+
+	list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead);
+#endif
+	psPrivateData->ui32OpenPID = ui32PID;
+	psPrivateData->hBlockAlloc = hBlockAlloc;
+	PRIVATE_DATA(pFile) = psPrivateData;
+	iRet = 0;
+err_unlock:	
+	LinuxUnLockMutex(&gPVRSRVLock);
+	return iRet;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		PVRSRVRelease
+
+ @Description
+
+ Release access the PVR services node - called when a file is closed, whether
+ at exit or using close(2) system call.
+
+ @input pInode - the inode for the file being released
+
+ @input pFile - the file handle data for the actual file being released
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM)
+void PVRSRVRelease(void *pvPrivData)
+#else
+static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+	PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+	int err = 0;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+#if defined(SUPPORT_DRI_DRM)
+	psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData;
+#else
+	psPrivateData = PRIVATE_DATA(pFile);
+#endif
+	if (psPrivateData != IMG_NULL)
+	{
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+		list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+
+		if(psPrivateData->hKernelMemInfo)
+		{
+			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+			/* Look up the meminfo we just exported */
+			if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+								  (IMG_PVOID *)&psKernelMemInfo,
+								  psPrivateData->hKernelMemInfo,
+								  PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+				err = -EFAULT;
+				goto err_unlock;
+			}
+
+			/* Tell the XProc about the export if required */
+			if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+			{
+				BM_XProcIndexRelease(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+			}
+
+			/* This drops the psMemInfo refcount bumped on export */
+			if(FreeMemCallBackCommon(psKernelMemInfo, 0,
+									 PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: FreeMemCallBackCommon failed", __FUNCTION__));
+				err = -EFAULT;
+				goto err_unlock;
+			}
+		}
+
+		/* Usually this is the same as OSGetCurrentProcessIDKM(),
+		 * but not necessarily (e.g. fork(), child closes last..)
+		 */
+		gui32ReleasePID = psPrivateData->ui32OpenPID;
+		PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
+		gui32ReleasePID = 0;
+
+		OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				  sizeof(PVRSRV_FILE_PRIVATE_DATA),
+				  psPrivateData, psPrivateData->hBlockAlloc);
+
+#if !defined(SUPPORT_DRI_DRM)
+		PRIVATE_DATA(pFile) = IMG_NULL; /*nulling shared pointer*/
+#endif
+	}
+
+err_unlock:
+	LinuxUnLockMutex(&gPVRSRVLock);
+#if defined(SUPPORT_DRI_DRM)
+	return;
+#else
+	return err;
+#endif
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		PVRCore_Init
+
+ @Description
+
+ Insert the driver into the kernel.
+
+ The device major number is allocated by the kernel dynamically.  This means
+ that the device node (nominally /dev/pvrsrv) will need to be re-made at boot
+ time if the number changes between subsequent loads of the module.  While the
+ number often stays constant between loads this is not guaranteed.  The node
+ is made as root on the shell with:
+
+ 		mknod /dev/pvrsrv c nnn 0
+
+ where nnn is the major number found in /proc/devices for DEVNAME and also
+ reported by the PVR_DPF() - look at the boot log using dmesg' to see this).
+
+ Currently the auto-generated script /etc/init.d/rc.pvr handles creation of
+ the device.  In other environments the device may be created either through
+ devfs or sysfs.
+
+ Readable proc-filesystem entries under /proc/pvr are created with
+ CreateProcEntries().  These can be read at runtime to get information about
+ the device (eg. 'cat /proc/pvr/vm')
+
+ __init places the function in a special memory section that the kernel frees
+ once the function has been run.  Refer also to module_init() macro call below.
+
+ @input none
+
+ @Return none
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM)
+int PVRCore_Init(void)
+#else
+static int __init PVRCore_Init(void)
+#endif
+{
+	int error;
+#if !defined(PVR_LDM_MODULE)
+	PVRSRV_ERROR eError;
+#endif
+#if !defined(SUPPORT_DRI_DRM) && defined(PVR_LDM_DEVICE_CLASS)
+	struct device *psDev;
+#endif
+
+
+
+#if !defined(SUPPORT_DRI_DRM)
+	/*
+	 * Must come before attempting to print anything via Services.
+	 * For DRM, the initialisation will already have been done.
+	 */
+	PVRDPFInit();
+#endif
+	PVR_TRACE(("PVRCore_Init"));
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+	LinuxInitMutex(&gsPMMutex);
+#endif
+	LinuxInitMutex(&gPVRSRVLock);
+
+	if (CreateProcEntries ())
+	{
+		error = -ENOMEM;
+		return error;
+	}
+
+	if (PVROSFuncInit() != PVRSRV_OK)
+	{
+		error = -ENOMEM;
+		goto init_failed;
+	}
+
+	PVRLinuxMUtilsInit();
+
+	if(LinuxMMInit() != PVRSRV_OK)
+	{
+		error = -ENOMEM;
+		goto init_failed;
+	}
+
+#if defined(SUPPORT_DMABUF)
+	if (PVRLinuxFenceInit())
+	{
+		error = -ENOMEM;
+		goto init_failed;
+	}
+#endif
+
+	LinuxBridgeInit();
+	
+	PVRMMapInit();
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE) || defined(SUPPORT_DRI_DRM_PLUGIN)
+	if ((error = platform_driver_register(&powervr_driver)) != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
+
+		goto init_failed;
+	}
+
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+	if ((error = platform_device_register(&powervr_device)) != 0)
+	{
+		platform_driver_unregister(&powervr_driver);
+
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
+
+		goto init_failed;
+	}
+#endif
+#endif /* PVR_LDM_PLATFORM_MODULE */
+
+#if defined(PVR_LDM_PCI_MODULE)
+	if ((error = pci_register_driver(&powervr_driver)) != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
+
+		goto init_failed;
+	}
+#endif /* PVR_LDM_PCI_MODULE */
+#endif /* defined(PVR_LDM_MODULE) */
+
+#if !defined(PVR_LDM_MODULE)
+	/*
+	 * Drivers using LDM, will call SysInitialise in the probe/attach code
+	 */
+	if ((eError = SysInitialise()) != PVRSRV_OK)
+	{
+		error = -ENODEV;
+#if defined(TCF_REV) && (TCF_REV == 110)
+		if(eError == PVRSRV_ERROR_NOT_SUPPORTED)
+		{
+			printk("\nAtlas wrapper (FPGA image) version mismatch");
+			error = -ENODEV;
+		}
+#endif
+		goto init_failed;
+	}
+#endif /* !defined(PVR_LDM_MODULE) */
+
+#if !defined(SUPPORT_DRI_DRM)
+	AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
+
+	if (AssignedMajorNumber <= 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
+
+		error = -EBUSY;
+		goto sys_deinit;
+	}
+
+	PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
+
+#if defined(PVR_LDM_DEVICE_CLASS)
+	/*
+	 * This code (using GPL symbols) facilitates automatic device
+	 * node creation on platforms with udev (or similar).
+	 */
+	psPvrClass = class_create(THIS_MODULE, "pvr");
+
+	if (IS_ERR(psPvrClass))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
+		error = -EBUSY;
+		goto unregister_device;
+	}
+
+	psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+				  NULL,
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
+				  DEVNAME);
+	if (IS_ERR(psDev))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
+		error = -EBUSY;
+		goto destroy_class;
+	}
+#endif /* defined(PVR_LDM_DEVICE_CLASS) */
+#endif /* !defined(SUPPORT_DRI_DRM) */
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	SystraceCreateFS();
+#endif
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	PVRSyncDeviceInit();
+#endif
+	return 0;
+
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(PVR_LDM_DEVICE_CLASS)
+destroy_class:
+	class_destroy(psPvrClass);
+unregister_device:
+	unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME);
+#endif
+#endif
+#if !defined(SUPPORT_DRI_DRM)
+sys_deinit:
+#endif
+#if defined(PVR_LDM_MODULE)
+#if defined(PVR_LDM_PCI_MODULE)
+	pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+	platform_device_unregister(&powervr_device);
+#endif
+	platform_driver_unregister(&powervr_driver);
+#endif
+
+#else	/* defined(PVR_LDM_MODULE) */
+	/* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */
+	{
+		SYS_DATA *psSysData;
+
+		psSysData = SysAcquireDataNoCheck();
+		if (psSysData != IMG_NULL)
+		{
+			(void) SysDeinitialise(psSysData);
+		}
+	}
+#endif	/* defined(PVR_LDM_MODULE) */
+init_failed:
+	PVRMMapCleanup();
+	LinuxMMCleanup();
+	LinuxBridgeDeInit();
+#if defined(SUPPORT_DMABUF)
+	PVRLinuxFenceDeInit();
+#endif
+	PVROSFuncDeInit();
+	RemoveProcEntries();
+	return error;
+
+} /*PVRCore_Init*/
+
+
+/*!
+*****************************************************************************
+
+ @Function		PVRCore_Cleanup
+
+ @Description	
+
+ Remove the driver from the kernel.
+
+ There's no way we can get out of being unloaded other than panicking; we
+ just do everything and plough on regardless of error.
+
+ __exit places the function in a special memory section that the kernel frees
+ once the function has been run.  Refer also to module_exit() macro call below.
+
+ Note that the for LDM on MontaVista kernels, the positioning of the driver
+ de-registration is the opposite way around than would be suggested by the
+ registration case or the 2,6 kernel case.  This is the correct way to do it
+ and the kernel panics if you change it.  You have been warned.
+
+ @input none
+
+ @Return none
+
+*****************************************************************************/
+#if defined(SUPPORT_DRI_DRM)
+void PVRCore_Cleanup(void)
+#else
+static void __exit PVRCore_Cleanup(void)
+#endif
+{
+#if !defined(PVR_LDM_MODULE)
+	SYS_DATA *psSysData;
+#endif
+	PVR_TRACE(("PVRCore_Cleanup"));
+
+#if !defined(PVR_LDM_MODULE)
+	SysAcquireData(&psSysData);
+#endif
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	PVRSyncDeviceDeInit();
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+
+#if defined(PVR_LDM_DEVICE_CLASS)
+	device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+	class_destroy(psPvrClass);
+#endif
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+	if (
+#endif	/* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
+		unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME)
+#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+								;
+#else	/* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
+								)
+	{
+		PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
+	}
+#endif	/* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
+#endif	/* !defined(SUPPORT_DRI_DRM) */
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PCI_MODULE)
+	pci_unregister_driver(&powervr_driver);
+#endif
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+	platform_device_unregister(&powervr_device);
+#endif
+	platform_driver_unregister(&powervr_driver);
+#endif
+
+#else /* defined(PVR_LDM_MODULE) */
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+	if (gPVRPowerLevel != 0)
+	{
+		if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+		{
+			gPVRPowerLevel = 0;
+		}
+	}
+#endif
+	/* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */
+	(void) SysDeinitialise(psSysData);
+#endif /* defined(PVR_LDM_MODULE) */
+
+	PVRMMapCleanup();
+
+	LinuxMMCleanup();
+
+	LinuxBridgeDeInit();
+
+#if defined(SUPPORT_DMABUF)
+	PVRLinuxFenceDeInit();
+#endif
+
+	PVROSFuncDeInit();
+
+	RemoveProcEntries();
+
+#if defined(SUPPORT_PVRSRV_ANDROID_SYSTRACE) && defined(EUR_CR_TIMER)
+	SystraceDestroyFS();
+#endif
+
+	PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver.  Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
+#if !defined(SUPPORT_DRI_DRM)
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
+#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c
new file mode 100644
index 0000000..56422d6
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.c
@@ -0,0 +1,163 @@
+/*************************************************************************/ /*!
+@Title          Linux mutex interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+#include <linux/errno.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/module.h>
+
+#include <img_defs.h>
+#include <services.h>
+
+#include "mutex.h"
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    mutex_init(psPVRSRVMutex);
+}
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    mutex_lock(psPVRSRVMutex);
+}
+
+IMG_VOID LinuxLockMutexNested(PVRSRV_LINUX_MUTEX *psPVRSRVMutex, unsigned int uiLockClass)
+{
+	mutex_lock_nested(psPVRSRVMutex, uiLockClass);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    if(mutex_lock_interruptible(psPVRSRVMutex) == -EINTR)
+    {
+        return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+    }
+    else
+    {
+        return PVRSRV_OK;
+    }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    return mutex_trylock(psPVRSRVMutex);
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    mutex_unlock(psPVRSRVMutex);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    return (mutex_is_locked(psPVRSRVMutex)) ? IMG_TRUE : IMG_FALSE;
+}
+
+
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
+
+
+IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    init_MUTEX(&psPVRSRVMutex->sSemaphore);
+    atomic_set(&psPVRSRVMutex->Count, 0);
+}
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    down(&psPVRSRVMutex->sSemaphore);
+    atomic_dec(&psPVRSRVMutex->Count);
+}
+
+IMG_VOID LinuxLockMutexNested(PVRSRV_LINUX_MUTEX *psPVRSRVMutex, unsigned int uiLockClass)
+{
+	LinuxLockMutex(psPVRSRVMutex);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    if(down_interruptible(&psPVRSRVMutex->sSemaphore) == -EINTR)
+    {
+        /* The process was sent a signal while waiting for the semaphore
+         * (e.g. a kill signal from userspace)
+         */
+        return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+    }else{
+        atomic_dec(&psPVRSRVMutex->Count);
+        return PVRSRV_OK;
+    }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    IMG_INT32 Status = down_trylock(&psPVRSRVMutex->sSemaphore);
+    if(Status == 0)
+    {
+        atomic_dec(&psPVRSRVMutex->Count);
+    }
+
+    return Status == 0;
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    atomic_inc(&psPVRSRVMutex->Count);
+    up(&psPVRSRVMutex->sSemaphore);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+    IMG_INT32 iCount;
+    
+    iCount = atomic_read(&psPVRSRVMutex->Count);
+
+    return (IMG_BOOL)iCount;
+}
+
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h
new file mode 100644
index 0000000..09ae46d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutex.h
@@ -0,0 +1,100 @@
+/*************************************************************************/ /*!
+@Title          Linux mutex interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+#ifndef __INCLUDED_LINUX_MUTEX_H_
+#define __INCLUDED_LINUX_MUTEX_H_
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+typedef struct mutex PVRSRV_LINUX_MUTEX;
+
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
+
+
+typedef struct {
+    struct semaphore sSemaphore;
+    /* since Linux's struct semaphore is intended to be
+     * opaque we don't poke inside for the count and
+     * instead we track it outselves. (So we can implement
+     * LinuxIsLockedMutex)
+     */
+    atomic_t Count;
+}PVRSRV_LINUX_MUTEX;
+
+#endif
+
+enum PVRSRV_MUTEX_LOCK_CLASS
+{
+	PVRSRV_LOCK_CLASS_POWER,
+	PVRSRV_LOCK_CLASS_BRIDGE,
+	PVRSRV_LOCK_CLASS_MMAP,
+	PVRSRV_LOCK_CLASS_MM_DEBUG,
+	PVRSRV_LOCK_CLASS_PVR_DEBUG,
+};
+
+extern IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_VOID LinuxLockMutexNested(PVRSRV_LINUX_MUTEX *psPVRSRVMutex, unsigned int uiLockClass);
+
+extern PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+
+#endif /* __INCLUDED_LINUX_MUTEX_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c
new file mode 100644
index 0000000..3afa61b
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.c
@@ -0,0 +1,179 @@
+/*************************************************************************/ /*!
+@Title          Linux memory interface support functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0))
+#define _PAGE_CACHE_WC pgprot_val(cachemode2pgprot(_PAGE_CACHE_MODE_WC))
+#endif
+
+#define	PAT_LINUX_X86_WC	1
+
+#define	PAT_X86_ENTRY_BITS	8
+
+#define	PAT_X86_BIT_PWT		1U
+#define	PAT_X86_BIT_PCD		2U
+#define	PAT_X86_BIT_PAT		4U
+#define	PAT_X86_BIT_MASK	(PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define	PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+	IMG_UINT ret = 0;
+	pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+	ret |= PROT_TO_PAT_INDEX(val, PAT);
+	ret |= PROT_TO_PAT_INDEX(val, PCD);
+	ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+	return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+	return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+	/*
+	 * cpu_has_pat indicates whether PAT support is available on the CPU,
+	 * but doesn't indicate if it has been enabled.
+	 */
+	if (boot_cpu_has(X86_FEATURE_PAT))/* PRQA S 3335 */ /* ignore 'no function declared' */
+	{
+		u64 pat;
+		IMG_UINT pat_index;
+		IMG_UINT pat_entry;
+
+		PVR_TRACE(("%s: PAT available", __FUNCTION__));
+		/*
+		 * There is no Linux API for finding out if write combining
+		 * is avaialable through the PAT, so we take the direct
+		 * approach, and see if the PAT MSR contains a write combining
+		 * entry.
+		 */
+		rdmsrl(MSR_IA32_CR_PAT, pat);
+		PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+		PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0))		
+		pat_index = pvr_pat_index(_PAGE_CACHE_MODE_WC);
+#else
+		pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+#endif
+		PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+		pat_entry = pvr_pat_entry(pat, pat_index);
+		PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+		g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+	}
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+	if (g_write_combining_available)
+	{
+		PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+	}
+	else
+	{
+		PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+	}
+#else	/* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */
+	PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif	/* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */
+#endif	/* DEBUG */
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+    /*
+     * It would be worth checking from time to time to see if a
+     * pgprot_writecombine function (or similar) is introduced on Linux for
+     * x86 processors.  If so, this function, and PVRLinuxX86PATProbe can be
+     * removed, and a macro used to select between pgprot_writecombine and
+     * pgprot_noncached, dpending on the value for of
+     * SUPPORT_LINUX_X86_WRITECOMBINE.
+     */
+    /* PRQA S 0481,0482 2 */ /* scalar expressions */
+    return (g_write_combining_available) ?
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0))		
+		__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_MODE_WC) : pgprot_noncached(prot);
+#else
+		__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+#endif
+}
+#endif	/* defined(SUPPORT_LINUX_X86_PAT) */
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+	PVRLinuxX86PATProbe();
+#endif
+}
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h
new file mode 100644
index 0000000..2cafc7e
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/mutils.h
@@ -0,0 +1,128 @@
+/*************************************************************************/ /*!
+@Title          Memory management support utils
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declares various memory management support functions
+                for Linux.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#if !(defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+	pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+	#define	PGPROT_WC(pv)	pvr_pgprot_writecombine(pv)
+#else
+	#if defined(__arm__) || defined(__aarch64__) || defined(__sh__)
+		#define	PGPROT_WC(pv)	pgprot_writecombine(pv)
+	#elif defined(__mips__)
+		#define PGPROT_WC(pv)	pgprot_writecombine(pv)
+	#elif defined(__i386__) || defined(__x86_64)
+		/* PAT support supersedes this */
+		#define	PGPROT_WC(pv)	pgprot_noncached(pv)
+	#else
+		#define PGPROT_WC(pv)	pgprot_noncached(pv)
+		#error  Unsupported architecture!
+	#endif
+#endif
+
+#define	PGPROT_UC(pv)	pgprot_noncached(pv)
+
+#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+	#define	IOREMAP(pa, bytes)	ioremap_cache(pa, bytes)
+#else	
+	#if defined(__arm__) || defined(__aarch64__)
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
+				#define	IOREMAP(pa, bytes)	ioremap_cache(pa, bytes)
+		#else
+			#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+				#define	IOREMAP(pa, bytes)	ioremap_cached(pa, bytes)
+			#else
+				#define IOREMAP(pa, bytes)	ioremap(pa, bytes)
+			#endif
+		#endif
+	#else
+		#define IOREMAP(pa, bytes)	ioremap(pa, bytes)
+	#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+	#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+		#define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+	#else
+		#define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+	#endif
+#else
+	#if defined(__arm__) || defined(__aarch64__)
+		#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+			#define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+		#else
+			#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+				#define	IOREMAP_WC(pa, bytes)	ioremap_nocache(pa, bytes)
+			#else
+				#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17))
+					#define	IOREMAP_WC(pa, bytes)	__ioremap(pa, bytes, L_PTE_BUFFERABLE)
+				#else
+					#define IOREMAP_WC(pa, bytes)	__ioremap(pa, bytes, , L_PTE_BUFFERABLE, 1)
+				#endif
+			#endif
+		#endif
+	#else
+		#define IOREMAP_WC(pa, bytes)	ioremap_nocache(pa, bytes)
+	#endif
+#endif
+
+#define	IOREMAP_UC(pa, bytes)	ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif /* __IMG_LINUX_MUTILS_H__ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c b/drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c
new file mode 100644
index 0000000..273b490
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/osfunc.c
@@ -0,0 +1,4850 @@
+/*************************************************************************/ /*!
+@Title          Environment related functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/io.h>
+#include <asm/page.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+#include <asm/system.h>
+#endif
+#include <asm/cacheflush.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h> 
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#if defined(MEM_TRACK_INFO_DEBUG) || defined (PVRSRV_DEVMEM_TIME_STATS)
+#include <linux/time.h>
+#endif
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+	defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+	defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+	defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) || \
+	defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "mutex.h"
+#include "event.h"
+#include "linkage.h"
+#include "pvr_uaccess.h"
+#include "lock.h"
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+#include "pvr_sync_common.h"
+#endif
+#if defined (SUPPORT_ION)
+#include "ion.h"
+#endif
+#if defined(SUPPORT_DMABUF)
+#include "pvr_linux_fence.h"
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
+#else
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
+#endif
+
+#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
+/* 
+ * Services spins at certain points waiting for events (e.g. swap
+ * chain destrucion).  If those events rely on workqueues running,
+ * it needs to be possible to preempt the waiting thread.
+ * Removing the need for CONFIG_PREEMPT will require adding preemption
+ * points at various points in Services.
+ */
+#error "A preemptible Linux kernel is required when using workqueues"
+#endif
+
+#if defined(EMULATOR)
+#define EVENT_OBJECT_TIMEOUT_MS		(2000)
+#else
+#define EVENT_OBJECT_TIMEOUT_MS		(100)
+#endif /* EMULATOR */
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+#else
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+    PVR_UNREFERENCED_PARAMETER(ui32Flags);
+    PVR_UNREFERENCED_PARAMETER(phBlockAlloc);
+
+    if (uiSize > PAGE_SIZE)
+    {
+        /* Try to allocate the memory using vmalloc */
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+        *ppvCpuVAddr = _VMallocWrapper(uiSize, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
+#else
+        *ppvCpuVAddr = VMallocWrapper(uiSize, PVRSRV_HAP_CACHED);
+#endif
+        if (*ppvCpuVAddr)
+        {
+            return PVRSRV_OK;
+        }
+    }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    *ppvCpuVAddr = _KMallocWrapper(uiSize, GFP_KERNEL | __GFP_NOWARN, pszFilename, ui32Line, ui32Flags & PVRSRV_SWAP_BUFFER_ALLOCATION);
+#else
+    *ppvCpuVAddr = KMallocWrapper(uiSize, GFP_KERNEL | __GFP_NOWARN);
+#endif
+    if (!*ppvCpuVAddr)
+    {
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    return PVRSRV_OK;
+}
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+
+static inline int is_vmalloc_addr(const void *pvCpuVAddr)
+{
+	unsigned long lAddr = (unsigned long)pvCpuVAddr;
+	return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
+}
+
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)) */
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+#else
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uiSize, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{	
+    PVR_UNREFERENCED_PARAMETER(ui32Flags);
+    PVR_UNREFERENCED_PARAMETER(uiSize);
+    PVR_UNREFERENCED_PARAMETER(hBlockAlloc);
+
+    if (is_vmalloc_addr(pvCpuVAddr))
+    {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+        _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+        VFreeWrapper(pvCpuVAddr);
+#endif
+    }
+    else
+    {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+        _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line, ui32Flags & PVRSRV_SWAP_BUFFER_ALLOCATION);
+#else
+        KFreeWrapper(pvCpuVAddr);
+#endif
+    }
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
+				  IMG_SIZE_T uiSize,
+				  IMG_UINT32 ui32PageSize,
+				  IMG_PVOID pvPrivData,
+				  IMG_UINT32 ui32PrivDataLength,
+				  IMG_HANDLE hBMHandle,
+				  IMG_VOID **ppvCpuVAddr,
+				  IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+#if 0
+    /* For debug: force all OSAllocPages allocations to have a kernel
+     * virtual address */
+    if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
+    {
+        ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+        ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
+    }
+#endif
+
+    switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+            psLinuxMemArea = NewVMallocLinuxMemArea(uiSize, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+            /* Currently PVRSRV_HAP_SINGLE_PROCESS implies that we dont need a
+             * kernel virtual mapping, but will need a user space virtual mapping */
+
+            psLinuxMemArea = NewAllocPagesLinuxMemArea(uiSize, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+             * virtual mapping and potentially multiple user space virtual
+             * mappings: Note: these eat into our limited kernel virtual
+             * address space. */
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+            /* ARM9 caches are tagged with virtual pages, not physical. As we are going to
+             * share this memory in different address spaces, we don't want it to be cached.
+             * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+             * address aliasing in the TLB, as long as the kernel supports cache colouring for
+             * VIPT architectures. */
+            ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+            psLinuxMemArea = NewVMallocLinuxMemArea(uiSize, ui32AllocFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_OUT_OF_MEMORY;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags));
+            *ppvCpuVAddr = NULL;
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+	/*
+		In case of sparse mapping we need to handle back to the BM as it
+		knows the mapping info
+	*/
+	if (ui32AllocFlags & PVRSRV_MEM_SPARSE)
+	{
+		psLinuxMemArea->hBMHandle = hBMHandle;
+	}
+
+    *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+    *phOSMemHandle = psLinuxMemArea;
+    
+    LinuxMemAreaRegister(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_SIZE_T uiBytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+{   
+    LinuxMemArea *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+    
+    PVR_UNREFERENCED_PARAMETER(uiBytes);
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+    
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+    switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+            eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+            if (eError != PVRSRV_OK)
+            {
+                PVR_DPF((PVR_DBG_ERROR,
+                         "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%" SIZE_T_FMT_LEN "u, "
+                                        "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+                         ui32AllocFlags, uiBytes, pvCpuVAddr, hOSMemHandle));
+                return eError;
+            }
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n",
+                    __FUNCTION__, ui32AllocFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+    }
+
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+                  IMG_UINTPTR_T uiByteOffset,
+                  IMG_SIZE_T uiBytes,
+                  IMG_UINT32 ui32Flags,
+                  IMG_HANDLE *phOSMemHandleRet)
+{
+    LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+
+    psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    
+    psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, uiByteOffset, uiBytes);
+    if(!psLinuxMemArea)
+    {
+        *phOSMemHandleRet = NULL;
+        return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+    *phOSMemHandleRet = psLinuxMemArea;
+
+    /* KERNEL_ONLY areas are never mmapable. */
+    if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+        return PVRSRV_OK;
+    }
+
+    eError = PVRMMapRegisterArea(psLinuxMemArea);
+    if(eError != PVRSRV_OK)
+    {
+        goto failed_register_area;
+    }
+
+    return PVRSRV_OK;
+
+failed_register_area:
+    *phOSMemHandleRet = NULL;
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+    return eError;
+}
+
+PVRSRV_ERROR
+OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+    
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+    
+    if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0)
+    {
+        eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+        if(eError != PVRSRV_OK)
+        {
+            return eError;
+        }
+    }
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+IMG_CPU_PHYADDR
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINTPTR_T uiByteOffset)
+{
+    PVR_ASSERT(hOSMemHandle);
+
+    return LinuxMemAreaToCpuPAddr(hOSMemHandle, uiByteOffset);
+}
+
+
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle)
+{
+	LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+	PVR_ASSERT(psLinuxMemArea);
+
+	if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV)
+		return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+	return IMG_FALSE;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSMemCopy
+
+ @Description	Copies memory around
+
+ @Input    pvDst - pointer to dst
+ @Output   pvSrc - pointer to src
+ @Input    ui32Size - bytes to copy
+
+ @Return  none
+
+******************************************************************************/
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T uiSize)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+    IMG_UINT8 *Src,*Dst;
+    IMG_INT i;
+
+    Src=(IMG_UINT8 *)pvSrc;
+    Dst=(IMG_UINT8 *)pvDst;
+    for(i=0;i<uiSize;i++)
+    {
+        Dst[i]=Src[i];
+    }
+#else
+    memcpy(pvDst, pvSrc, uiSize);
+#endif
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	OSMemSet
+
+ @Description Function that does the same as the C memset() functions
+
+ @Modified *pvDest :	pointer to start of buffer to be set
+
+ @Input    ui8Value:	value to set each byte to
+
+ @Input    ui32Size :	number of bytes to set
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T uiSize)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+    IMG_UINT8 *Buff;
+    IMG_INT i;
+
+    Buff=(IMG_UINT8 *)pvDest;
+    for(i=0;i<uiSize;i++)
+    {
+        Buff[i]=ui8Value;
+    }
+#else
+    memset(pvDest, (IMG_INT) ui8Value, (size_t) uiSize);
+#endif
+}
+
+
+/*!
+******************************************************************************
+ @Function	OSStringCopy
+ @Description strcpy
+******************************************************************************/
+IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+    return (strcpy(pszDest, pszSrc));
+}
+
+/*!
+******************************************************************************
+ @Function	OSSNPrintf
+ @Description snprintf
+******************************************************************************/
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T uiSize, const IMG_CHAR *pszFormat, ...)
+{
+    va_list argList;
+    IMG_INT32 iCount;
+
+    va_start(argList, pszFormat);
+    iCount = vsnprintf(pStr, (size_t)uiSize, pszFormat, argList);
+    va_end(argList);
+
+    return iCount;
+}
+
+/*!
+******************************************************************************
+
+ @Function OSBreakResourceLock
+
+ @Description unlocks an OS dependant resource
+
+ @Input phResource - pointer to OS dependent resource structure
+ @Input ui32ID - Lock value to look for
+
+ @Return
+
+******************************************************************************/
+IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+    if(*pui32Access)
+    {
+        if(psResource->ui32ID == ui32ID)
+        {
+            psResource->ui32ID = 0;
+            *pui32Access = 0;
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process.")); 
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked"));
+    }
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSCreateResource
+
+ @Description creates a OS dependant resource object
+
+ @Input phResource - pointer to OS dependent resource
+
+ @Return error status
+
+******************************************************************************/
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
+{
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	PVRSRV_ERROR eError = PVRSRV_OK;
+#endif
+
+    psResource->ui32ID = 0;
+    psResource->ui32Lock = 0;
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	psResource->pOSSyncPrimitive = IMG_NULL;
+
+	eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(spinlock_t), (IMG_VOID**)&psResource->pOSSyncPrimitive, IMG_NULL,
+		"Resource Spinlock");
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"OSCreateResource: Spinlock could not be alloc'd"));
+		return eError;
+	}
+
+	spin_lock_init((spinlock_t*)psResource->pOSSyncPrimitive);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSDestroyResource
+
+ @Description destroys an OS dependant resource object
+
+ @Input phResource - pointer to OS dependent resource
+
+ @Return error status
+
+******************************************************************************/
+PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
+{
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+	if (psResource->pOSSyncPrimitive)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(spinlock_t), (IMG_VOID*)psResource->pOSSyncPrimitive, IMG_NULL);
+	}
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+
+    OSBreakResourceLock (psResource, psResource->ui32ID);
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+  @Function		OSInitEnvData
+
+  @Description	Allocates space for env specific data
+
+  @Input		ppvEnvSpecificData - pointer to pointer in which to return
+                allocated data.
+  @Input		ui32MMUMode - MMU mode.
+
+  @Return		nothing
+
+******************************************************************************/
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
+{
+    ENV_DATA		*psEnvData;
+    PVRSRV_ERROR	eError;
+    
+    /* allocate env specific data */
+    eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
+        "Environment Data");
+    if (eError != PVRSRV_OK)
+    {
+        return eError;
+    }
+
+    eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, 
+                    &psEnvData->pvBridgeData, IMG_NULL,
+                    "Bridge Data");
+    if (eError != PVRSRV_OK)
+    {
+        OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
+		/*not nulling pointer, out of scope*/
+        return eError;
+    }
+
+
+    /* ISR installation flags */
+    psEnvData->bMISRInstalled = IMG_FALSE;
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    /* copy structure back */
+    *ppvEnvSpecificData = psEnvData;
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSDeInitEnvData
+
+ @Description	frees env specific data memory
+
+ @Input    pvEnvSpecificData - pointer to private structure
+
+ @Return   PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY
+
+******************************************************************************/
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
+{
+    ENV_DATA		*psEnvData = (ENV_DATA*)pvEnvSpecificData;
+
+    PVR_ASSERT(!psEnvData->bMISRInstalled);
+    PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL);
+    psEnvData->pvBridgeData = IMG_NULL;
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSReleaseThreadQuanta
+ 
+ @Description
+    Releases thread quanta
+     
+ @Return nothing
+
+******************************************************************************/ 
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
+{
+    schedule();
+}
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+/*!
+******************************************************************************
+
+ @Function OSClockMonotonicus
+
+ @Description	This function returns the raw monotonic clock time in microseconds
+				(i.e. un-affected by NTP or similar changes)
+
+ @Input void
+
+ @Return - monotonic clock time in (us)
+
+******************************************************************************/ 
+IMG_UINT64 OSClockMonotonicus(IMG_VOID)
+{
+	struct timespec ts;
+
+	getrawmonotonic(&ts);
+
+	return ((unsigned long)ts.tv_sec * 1000000ul + (unsigned long)ts.tv_nsec / 1000ul);
+}
+#endif
+
+
+/*!
+******************************************************************************
+
+ @Function OSClockus
+ 
+ @Description 
+    This function returns the clock in microseconds
+ 
+ @Input void
+
+ @Return - clock (us)
+
+******************************************************************************/ 
+IMG_UINT32 OSClockus(IMG_VOID)
+{
+    IMG_UINT32 time, j = jiffies;
+
+    time = j * (1000000 / HZ);
+
+    return time;
+}
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
+{
+    udelay(ui32Timeus);
+}
+
+
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems)
+{
+    msleep(ui32Timems);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerCreate
+ 
+ @Description 
+    This function creates a high res timer who's handle is returned
+ 
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/ 
+IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID)
+{
+	/* We don't need a handle, but we must return non-NULL */
+	return (IMG_HANDLE) 1;
+}
+
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerGetus
+ 
+ @Description 
+    This function returns the current timestamp in us
+ 
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/ 
+IMG_UINT32 OSFuncHighResTimerGetus(IMG_HANDLE hTimer)
+{
+	return (IMG_UINT32) jiffies_to_usecs(jiffies);
+}
+
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerDestroy
+ 
+ @Description 
+    This function will destroy the high res timer
+ 
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/ 
+IMG_VOID OSFuncHighResTimerDestroy(IMG_HANDLE hTimer)
+{
+	PVR_UNREFERENCED_PARAMETER(hTimer);
+}
+
+/*!
+******************************************************************************
+
+  @Function            OSGetCurrentProcessIDKM
+
+  @Description Returns handle for current process
+
+  @Return    ID of current process
+
+*****************************************************************************/
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
+{
+    if (in_interrupt())
+    {
+        return KERNEL_ID;
+    }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+    return (IMG_UINT32)current->pgrp;
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+    return (IMG_UINT32)task_tgid_nr(current);
+#else
+    return (IMG_UINT32)current->tgid;
+#endif
+#endif
+}
+
+#if defined(MEM_TRACK_INFO_DEBUG)
+/*!
+******************************************************************************
+
+  @Function            OSGetCurrentTimeInUSecsKM
+ 
+  @Description Returns current time in usecs
+
+  @Return    ID of current process
+
+*****************************************************************************/
+IMG_UINT32 OSGetCurrentTimeInUSecsKM(IMG_VOID)
+{
+	struct timeval          tv;
+	do_gettimeofday(&tv);
+	return (tv.tv_sec * 1000000 + tv.tv_usec);
+}
+#endif
+
+/*!
+******************************************************************************
+
+ @Function		OSGetPageSize
+ 
+ @Description	gets page size
+    
+ @Return   		page size
+
+******************************************************************************/
+IMG_UINT32 OSGetPageSize(IMG_VOID)
+{
+#if defined(__sh__)
+    IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
+
+    return (ui32ReturnValue);
+#else
+    return PAGE_SIZE;
+#endif
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+/*!
+******************************************************************************
+
+ @Function		DeviceISRWrapper
+ 
+ @Description	wrapper for Device ISR function to conform to ISR OS interface
+    
+ @Return
+
+******************************************************************************/
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+        , struct pt_regs *regs
+#endif
+        )
+{
+    PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id;
+    SYS_DATA *psSysData = psDeviceNode->psSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+    IMG_BOOL bStatus = IMG_FALSE;
+
+    PVR_UNREFERENCED_PARAMETER(irq);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+    PVR_UNREFERENCED_PARAMETER(regs);
+#endif	
+
+    if (psEnvData->bLISRInstalled)
+    {
+        bStatus = PVRSRVDeviceLISR(psDeviceNode);
+        if (bStatus)
+        {
+	    OSScheduleMISR((IMG_VOID *)psSysData);
+        }
+    }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+    return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function		SystemISRWrapper
+ 
+ @Description	wrapper for System ISR function to conform to ISR OS interface
+
+ @Input    Interrupt - NT interrupt object.
+ @Input    Context - Context parameter 
+    
+ @Return
+
+******************************************************************************/
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+        , struct pt_regs *regs
+#endif
+        )
+{
+    SYS_DATA *psSysData = (SYS_DATA *)dev_id;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+    IMG_BOOL bStatus = IMG_FALSE;
+
+    PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+    PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+
+    if (psEnvData->bLISRInstalled)
+    {
+        bStatus = PVRSRVSystemLISR(psSysData);
+        if (bStatus)
+        {
+            OSScheduleMISR((IMG_VOID *)psSysData);
+        }
+    }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+    return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+/*!
+******************************************************************************
+
+ @Function		OSInstallDeviceLISR
+ 
+ @Description	Installs a Device ISR
+    
+ @Input    pvSysData
+ @Input    ui32Irq - IRQ number
+ @Input    pszISRName - ISR name
+ @Input    pvDeviceNode - device node contains ISR function and data argument
+
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+                                    IMG_UINT32 ui32Irq,
+                                    IMG_CHAR *pszISRName,
+                                    IMG_VOID *pvDeviceNode)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+        return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+    }
+
+    PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %p", pszISRName, ui32Irq, pvDeviceNode));
+
+    if(request_irq(ui32Irq, DeviceISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+        SA_SHIRQ
+#else
+        IRQF_SHARED
+#endif
+        , pszISRName, pvDeviceNode))
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq));
+
+        return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+    }
+
+    psEnvData->ui32IRQ = ui32Irq;
+    psEnvData->pvISRCookie = pvDeviceNode;
+    psEnvData->bLISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;	
+}
+
+/*!
+******************************************************************************
+
+ @Function		OSUninstallDeviceLISR
+ 
+ @Description	Uninstalls a Device ISR
+    
+ @Input    pvSysData - sysdata
+
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed"));
+        return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+    }
+        
+    PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ,  psEnvData->pvISRCookie));
+
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSInstallSystemLISR
+ 
+ @Description	Installs a System ISR
+    
+ @Input    psSysData
+ @Input    ui32Irq - IRQ number
+
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+        return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+    }
+
+    PVR_TRACE(("Installing system LISR on IRQ %d with cookie %p", ui32Irq, pvSysData));
+
+    if(request_irq(ui32Irq, SystemISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+        SA_SHIRQ
+#else
+        IRQF_SHARED
+#endif
+        , PVRSRV_MODNAME, pvSysData))
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq));
+
+        return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+    }
+
+    psEnvData->ui32IRQ = ui32Irq;
+    psEnvData->pvISRCookie = pvSysData;
+    psEnvData->bLISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;	
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSUninstallSystemLISR
+ 
+ @Description	Uninstalls a System ISR
+    
+ @Input    psSysData
+
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bLISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed"));
+        return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+    }
+
+    PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+    psEnvData->bLISRInstalled = IMG_FALSE;
+
+    free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+    return PVRSRV_OK;
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+/*!
+******************************************************************************
+
+ @Function		MISRWrapper
+ 
+ @Description	OS dependent MISR wrapper
+	
+ @Input    psSysData
+
+ @Return   error status 
+
+******************************************************************************/
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+			void *data
+#else
+			struct work_struct *data
+#endif
+)
+{
+	ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+	SYS_DATA *psSysData  = (SYS_DATA *)psEnvData->pvMISRData;
+
+	PVRSRVMISR(psSysData);
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	PVRSyncUpdateAllSyncs();
+#endif
+#if defined(SUPPORT_DMABUF)
+	PVRLinuxFenceCheckAll();
+#endif
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSInstallMISR
+ 
+ @Description	Installs an OS dependent MISR
+
+ @Input    psSysData
+	
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+	ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+	if (psEnvData->bMISRInstalled)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+		return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+	}
+
+	PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+	psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+	if (psEnvData->psWorkQueue == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+		return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+	}
+
+	INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+		, (void *)&psEnvData->sMISRWork
+#endif
+				);
+
+	psEnvData->pvMISRData = pvSysData;
+	psEnvData->bMISRInstalled = IMG_TRUE;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSUninstallMISR
+ 
+ @Description	Uninstalls an OS dependent MISR
+
+ @Input    psSysData
+	
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+	ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+	if (!psEnvData->bMISRInstalled)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+		return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+	}
+
+	PVR_TRACE(("Uninstalling MISR"));
+
+	destroy_workqueue(psEnvData->psWorkQueue);
+
+	psEnvData->bMISRInstalled = IMG_FALSE;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSScheduleMISR
+ 
+ @Description	Schedules an OS dependent MISR
+
+ @Input    pvSysData
+	
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+	ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+	if (psEnvData->bMISRInstalled)
+	{
+		queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork);
+	}
+
+	return PVRSRV_OK;	
+}
+#else	/* defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+/*!
+******************************************************************************
+
+ @Function		MISRWrapper
+ 
+ @Description	OS dependent MISR wrapper
+	
+ @Input    psSysData
+
+ @Return   error status 
+
+******************************************************************************/
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+			void *data
+#else
+			struct work_struct *data
+#endif
+)
+{
+	ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+	SYS_DATA *psSysData  = (SYS_DATA *)psEnvData->pvMISRData;
+
+	PVRSRVMISR(psSysData);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSInstallMISR
+ 
+ @Description	Installs an OS dependent MISR
+
+ @Input    psSysData
+	
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+	ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+	if (psEnvData->bMISRInstalled)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+		return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+	}
+
+	PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+	INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+		, (void *)&psEnvData->sMISRWork
+#endif
+				);
+
+	psEnvData->pvMISRData = pvSysData;
+	psEnvData->bMISRInstalled = IMG_TRUE;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSUninstallMISR
+ 
+ @Description	Uninstalls an OS dependent MISR
+
+ @Input    psSysData
+	
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+	ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+	if (!psEnvData->bMISRInstalled)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+		return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+	}
+
+	PVR_TRACE(("Uninstalling MISR"));
+
+	flush_scheduled_work();
+
+	psEnvData->bMISRInstalled = IMG_FALSE;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSScheduleMISR
+ 
+ @Description	Schedules an OS dependent MISR
+
+ @Input    pvSysData
+	
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+	SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+	ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+	if (psEnvData->bMISRInstalled)
+	{
+		schedule_work(&psEnvData->sMISRWork);
+	}
+
+	return PVRSRV_OK;	
+}
+
+#else	/* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+
+
+/*!
+******************************************************************************
+
+ @Function		MISRWrapper
+ 
+ @Description	OS dependent MISR wrapper
+    
+ @Input    psSysData
+
+ @Return   error status 
+
+******************************************************************************/
+static void MISRWrapper(unsigned long data)
+{
+    SYS_DATA *psSysData;
+
+    psSysData = (SYS_DATA *)data;
+    
+    PVRSRVMISR(psSysData);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSInstallMISR
+ 
+ @Description	Installs an OS dependent MISR
+
+ @Input    psSysData
+    
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bMISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+        return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+    }
+
+    PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+    tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData);
+
+    psEnvData->bMISRInstalled = IMG_TRUE;
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSUninstallMISR
+ 
+ @Description	Uninstalls an OS dependent MISR
+
+ @Input    psSysData
+    
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+    if (!psEnvData->bMISRInstalled)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+        return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+    }
+
+    PVR_TRACE(("Uninstalling MISR"));
+
+    tasklet_kill(&psEnvData->sMISRTasklet);
+
+    psEnvData->bMISRInstalled = IMG_FALSE;
+
+    return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function		OSScheduleMISR
+ 
+ @Description	Schedules an OS dependent MISR
+
+ @Input    pvSysData
+    
+ @Return   error status 
+
+******************************************************************************/
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+    SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+    ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+    if (psEnvData->bMISRInstalled)
+    {
+        tasklet_schedule(&psEnvData->sMISRTasklet);
+    }
+
+    return PVRSRV_OK;	
+}
+
+#endif /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+#endif /* #if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
+
+#endif /* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) */
+
+IMG_VOID OSPanic(IMG_VOID)
+{
+	BUG();
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#define	OS_TAS(p)	xchg((p), 1)
+#else
+#define	OS_TAS(p)	tas(p)
+#endif
+/*!
+******************************************************************************
+
+ @Function OSLockResource
+
+ @Description locks an OS dependant Resource
+
+ @Input phResource - pointer to OS dependent Resource
+ @Input bBlock - do we want to block?
+
+ @Return error status
+
+******************************************************************************/
+PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE 	*psResource,
+                                IMG_UINT32 			ui32ID)
+
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(!OS_TAS(&psResource->ui32Lock))
+        psResource->ui32ID = ui32ID;
+    else
+        eError = PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE;
+
+    return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSUnlockResource
+
+ @Description unlocks an OS dependant resource
+
+ @Input phResource - pointer to OS dependent resource structure
+
+ @Return
+
+******************************************************************************/
+PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(*pui32Access)
+    {
+        if(psResource->ui32ID == ui32ID)
+        {
+            psResource->ui32ID = 0;
+            smp_mb();
+            *pui32Access = 0;
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource)); 
+            PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+            eError = PVRSRV_ERROR_INVALID_LOCK_ID;
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource));
+        eError = PVRSRV_ERROR_RESOURCE_NOT_LOCKED;
+    }
+    
+    return eError;
+}
+
+
+#if !defined(PVR_LINUX_USING_WORKQUEUES)
+/*!
+******************************************************************************
+
+ @Function OSLockResourceAndBlockMISR
+
+ @Description locks an OS dependant Resource and blocks MISR interrupts
+
+ @Input phResource - pointer to OS dependent Resource
+ @Input bBlock - do we want to block?
+
+ @Return error status
+
+******************************************************************************/
+PVRSRV_ERROR OSLockResourceAndBlockMISR ( PVRSRV_RESOURCE 	*psResource,
+								IMG_UINT32 			ui32ID)
+
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	spin_lock_bh(psResource->pOSSyncPrimitive);
+
+	if(!OS_TAS(&psResource->ui32Lock))
+		psResource->ui32ID = ui32ID;
+	else
+		eError = PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE;
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSUnlockResourceAndUnblockMISR
+
+ @Description unlocks an OS dependant resource and unblocks MISR interrupts
+
+ @Input phResource - pointer to OS dependent resource structure
+
+ @Return
+
+******************************************************************************/
+PVRSRV_ERROR OSUnlockResourceAndUnblockMISR (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+	volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if(*pui32Access)
+	{
+		if(psResource->ui32ID == ui32ID)
+		{
+			psResource->ui32ID = 0;
+			smp_mb();
+			*pui32Access = 0;
+			spin_unlock_bh(psResource->pOSSyncPrimitive);
+		}
+		else
+		{
+			PVR_DPF((PVR_DBG_ERROR,"OSUnlockResourceAndUnblockMISR: Resource %p is not locked with expected value.", psResource));
+			PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+			eError = PVRSRV_ERROR_INVALID_LOCK_ID;
+		}
+	}
+	else
+	{
+		PVR_DPF((PVR_DBG_ERROR,"OSUnlockResourceAndUnblockMISR: Resource %p is not locked", psResource));
+		eError = PVRSRV_ERROR_RESOURCE_NOT_LOCKED;
+	}
+
+	return eError;
+}
+#endif
+
+
+/*!
+******************************************************************************
+
+ @Function OSIsResourceLocked
+
+ @Description tests if resource is locked
+
+ @Input phResource - pointer to OS dependent resource structure
+
+ @Return error status
+
+******************************************************************************/
+IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+    volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+    return 	(*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID)
+            ?	IMG_TRUE
+            :	IMG_FALSE;
+}
+
+
+#if !defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock)
+{
+	PVR_UNREFERENCED_PARAMETER(bTryLock);	
+
+	return PVRSRV_OK;
+}
+
+IMG_VOID OSPowerLockUnwrap (IMG_VOID)
+{
+}
+#endif /* SYS_CUSTOM_POWERLOCK_WRAP */
+
+
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
+								  IMG_VOID *pvLinAddr)
+{
+    IMG_CPU_PHYADDR CpuPAddr;
+    LinuxMemArea *psLinuxMemArea;
+	IMG_UINTPTR_T uiByteOffset;
+	IMG_UINT32 ui32ByteOffset;
+
+	PVR_ASSERT(hOSMemHandle != IMG_NULL);
+
+	psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+	uiByteOffset = (IMG_UINTPTR_T)pvLinAddr - (IMG_UINTPTR_T)LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+	ui32ByteOffset = (IMG_UINT32)uiByteOffset;
+
+	CpuPAddr = LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+
+	return CpuPAddr;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		OSMapPhysToLin
+
+ @Description	Maps the physical memory into linear addr range
+
+ @Input    BasePAddr : physical cpu address
+
+ @Input    ui32Bytes - bytes to map
+
+ @Input    ui32CacheType - cache type
+
+ @Return    : Linear addr of mapping on success, else NULL
+
+ ******************************************************************************/
+IMG_VOID *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+               IMG_SIZE_T uiBytes,
+               IMG_UINT32 ui32MappingFlags,
+               IMG_HANDLE *phOSMemHandle)
+{
+    if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+	/* 
+	 * Provide some backwards compatibility, until all callers
+	 * have been updated to pass a non-null OSMemHandle pointer.
+	 * Such callers must not call OSMapLinToCPUPhys.
+	 */
+	if(phOSMemHandle == IMG_NULL)
+	{
+		IMG_VOID *pvIORemapCookie;
+		pvIORemapCookie = IORemapWrapper(BasePAddr, uiBytes, ui32MappingFlags);
+		if(pvIORemapCookie == IMG_NULL)
+		{
+		    return IMG_NULL;
+		}
+		return pvIORemapCookie;
+	}
+	else
+	{
+		LinuxMemArea *psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
+
+		if(psLinuxMemArea == IMG_NULL)
+		{
+		    return IMG_NULL;
+		}
+
+		*phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+		return LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+	}
+    }
+
+    PVR_DPF((PVR_DBG_ERROR,
+             "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+             " (Use OSReservePhys otherwise)"));
+
+    return IMG_NULL;
+}
+
+/*!
+******************************************************************************
+ @Function	OSUnMapPhysToLin
+ @Description Unmaps memory that was mapped with OSMapPhysToLin
+ @Return TRUE on success, else FALSE
+******************************************************************************/
+IMG_BOOL
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T uiBytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
+{
+    PVR_UNREFERENCED_PARAMETER(uiBytes);	
+
+    if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+    {
+        if (hOSMemHandle == IMG_NULL)
+	{
+		IOUnmapWrapper(pvLinAddr);
+	}
+	else
+	{
+		LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+		PVR_ASSERT(LinuxMemAreaToCpuVAddr(psLinuxMemArea) == pvLinAddr);
+		
+		FreeIORemapLinuxMemArea(psLinuxMemArea);
+	}
+
+        return IMG_TRUE;
+    }
+
+    PVR_DPF((PVR_DBG_ERROR,
+                 "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+                 " (Use OSUnReservePhys otherwise)"));
+    return IMG_FALSE;
+}
+
+/*!
+******************************************************************************
+ @Function	RegisterExternalMem
+ @Description Registers external memory for user mode mapping
+ @Return TRUE on success, else FALSE, MemHandle out
+******************************************************************************/
+static PVRSRV_ERROR
+RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
+          IMG_VOID *pvCPUVAddr,
+              IMG_UINT32 ui32Bytes,
+          IMG_BOOL bPhysContig,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+        
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+             * virtual mapping and potentially multiple user space virtual mappings.
+             * Beware that the kernel virtual address space is a limited resource.
+             */
+#if defined(VIVT_CACHE) || defined(__sh__)
+            /* 
+             * ARM9 caches are tagged with virtual pages, not physical. As we are going to
+             * share this memory in different address spaces, we don't want it to be cached.
+             * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+             * address aliasing in the TLB, as long as the kernel supports cache colouring for
+             * VIPT architectures.
+             */
+            ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+        psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags));
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_INVALID_FLAGS;
+    }
+    
+    *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+
+    LinuxMemAreaRegister(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+ @Function	OSRegisterMem
+ @Description Registers external memory for user mode mapping
+ @Output phOSMemHandle - handle to registered memory
+ @Return TRUE on success, else FALSE
+******************************************************************************/
+PVRSRV_ERROR
+OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+              IMG_VOID *pvCPUVAddr,
+              IMG_SIZE_T uiBytes,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_HANDLE *phOSMemHandle)
+{
+    IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+    return RegisterExternalMem(&SysPAddr, pvCPUVAddr, uiBytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+{
+    return RegisterExternalMem(pBasePAddr, pvCPUVAddr, uBytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+/*!
+******************************************************************************
+ @Function	OSUnRegisterMem
+ @Description UnRegisters external memory for user mode mapping
+ @Return TRUE on success, else FALSE
+******************************************************************************/
+PVRSRV_ERROR
+OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
+                IMG_SIZE_T uiBytes,
+                IMG_UINT32 ui32MappingFlags,
+                IMG_HANDLE hOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    PVRSRV_ERROR eError;
+
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+    PVR_UNREFERENCED_PARAMETER(uiBytes);
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+            if (eError != PVRSRV_OK)
+            {
+                 PVR_DPF((PVR_DBG_ERROR, "%s(%p, %" SIZE_T_FMT_LEN "u, 0x%08X, %p) FAILED!",
+                          __FUNCTION__, pvCpuVAddr, uiBytes,
+                          ui32MappingFlags, hOSMemHandle));
+                return eError;
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+    return OSUnRegisterMem(pvCpuVAddr, uBytes, ui32Flags, hOSMemHandle);
+}
+
+/*!
+******************************************************************************
+ @Function	OSReservePhys
+ @Description Registers physical memory for user mode mapping
+ @Output    ppvCpuVAddr
+ @Output    phOsMemHandle handle to registered memory
+ @Return TRUE on success, else FALSE
+******************************************************************************/
+PVRSRV_ERROR
+OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+              IMG_SIZE_T uiBytes,
+              IMG_UINT32 ui32MappingFlags,
+              IMG_HANDLE hBMHandle,
+              IMG_VOID **ppvCpuVAddr,
+              IMG_HANDLE *phOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+
+#if 0
+    /* For debug: force all OSReservePhys reservations to have a kernel
+     * virtual address */
+    if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
+    {
+        ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+        ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
+    }
+#endif
+
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+        {
+            /* Currently PVRSRV_HAP_KERNEL_ONLY implies that a kernel virtual
+             * mapping is required for the allocation and no user virtual
+             * mappings are allowed: Note these eat into our limited kernel
+             * virtual address space */
+            psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            break;
+        }
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        {
+            /* Currently this implies that we dont need a kernel virtual
+             * mapping, but will need a user space virtual mapping */
+            psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+             * virtual mapping and potentially multiple user space virtual mappings.
+             * Beware that the kernel virtual address space is a limited resource.
+             */
+#if defined(VIVT_CACHE) || defined(__sh__)
+            /* 
+             * ARM9 caches are tagged with virtual pages, not physical. As we are going to
+             * share this memory in different address spaces, we don't want it to be cached.
+             * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+             * address aliasing in the TLB, as long as the kernel supports cache colouring for
+             * VIPT architectures.
+             */
+            ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+            psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, uiBytes, ui32MappingFlags);
+            if(!psLinuxMemArea)
+            {
+                return PVRSRV_ERROR_BAD_MAPPING;
+            }
+            PVRMMapRegisterArea(psLinuxMemArea);
+            break;
+        }
+        default:
+            PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags));
+            *ppvCpuVAddr = NULL;
+            *phOSMemHandle = (IMG_HANDLE)0;
+            return PVRSRV_ERROR_INVALID_FLAGS;
+    }
+
+	/*
+		In case of sparse mapping we need to handle back to the BM as it
+		knows the mapping info
+	*/
+	if (ui32MappingFlags & PVRSRV_MEM_SPARSE)
+	{
+		PVR_ASSERT(hBMHandle != IMG_NULL);
+		psLinuxMemArea->hBMHandle = hBMHandle;
+	}
+
+    *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+    *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+    LinuxMemAreaRegister(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+ @Function	OSUnReservePhys
+ @Description UnRegisters physical memory for user mode mapping
+ @Return TRUE on success, else FALSE
+******************************************************************************/
+PVRSRV_ERROR
+OSUnReservePhys(IMG_VOID *pvCpuVAddr,
+                IMG_SIZE_T uiBytes,
+                IMG_UINT32 ui32MappingFlags,
+                IMG_HANDLE hOSMemHandle)
+{
+    LinuxMemArea *psLinuxMemArea;
+    PVRSRV_ERROR eError;
+
+    PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+    PVR_UNREFERENCED_PARAMETER(uiBytes);
+
+    psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+    
+    switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+    {
+        case PVRSRV_HAP_KERNEL_ONLY:
+            break;
+        case PVRSRV_HAP_SINGLE_PROCESS:
+        case PVRSRV_HAP_MULTI_PROCESS:
+        {
+            eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+            if (eError != PVRSRV_OK)
+            {
+                 PVR_DPF((PVR_DBG_ERROR, "%s(%p, %" SIZE_T_FMT_LEN "u, 0x%08X, %p) FAILED!",
+                          __FUNCTION__, pvCpuVAddr, uiBytes,
+                          ui32MappingFlags, hOSMemHandle));
+                return eError;
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags));
+            return PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+    
+    LinuxMemAreaDeepFree(psLinuxMemArea);
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+ @Function	OSBaseAllocContigMemory
+ @Description Allocate a block of contiguous virtual non-paged memory.
+ @Input     ui32Size - number of bytes to allocate
+ @Output    ppvLinAddr - pointer to variable that will receive the linear address of buffer
+ @Return PVRSRV_OK if allocation successed else returns PVRSRV_ERROR_OUT_OF_MEMORY
+ **************************************************************************/
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T uiSize, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+    PVR_UNREFERENCED_PARAMETER(uiSize);
+    PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+    PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
+
+    return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+/*
+ * On Linux, the returned virtual address should be used for CPU access,
+ * and not be remapped into the CPU virtual address using ioremap.  The fact
+ * that the RAM is being managed by the kernel, and already has a virtual
+ * address, seems to lead to problems when the attributes of the memory are
+ * changed in the ioremap call (such as from cached to non-cached).
+ */
+    IMG_VOID *pvKernLinAddr;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+    pvKernLinAddr = _KMallocWrapper(uiSize, GFP_KERNEL, __FILE__, __LINE__, IMG_FALSE);
+#else
+    pvKernLinAddr = KMallocWrapper(uiSize, GFP_KERNEL);
+#endif
+    if (!pvKernLinAddr)
+    {
+    return PVRSRV_ERROR_OUT_OF_MEMORY;
+    }
+
+    *pvLinAddr = pvKernLinAddr;
+
+    psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+    return PVRSRV_OK;
+#endif	/* !defined(NO_HARDWARE) */
+}
+
+
+/*!
+******************************************************************************
+ @Function	OSBaseFreeContigMemory
+ @Description Frees memory allocated with OSBaseAllocContigMemory
+ @Input     LinAddr - pointer to buffer allocated with OSBaseAllocContigMemory
+ **************************************************************************/
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T uiSize, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+    PVR_UNREFERENCED_PARAMETER(uiSize);
+    PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+    PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+    PVR_UNREFERENCED_PARAMETER(uiSize);
+    PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+    KFreeWrapper(pvLinAddr);
+#endif
+    return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSWriteHWReg
+ 
+ @Description 
+ 
+ register access function
+
+ @input pvLinRegBaseAddr :	lin addr of register block base
+
+ @input ui32Offset :	 
+
+ @input ui32Value :	
+ 
+ @Return   none
+
+******************************************************************************/
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+    return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+    return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+    writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+    *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+#endif
+}
+
+#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+
+/*!
+******************************************************************************
+
+ @Function	OSPCISetDev
+ 
+ @Description 
+ 
+ Set a PCI device for subsequent use.
+
+ @input pvPCICookie :	Pointer to OS specific PCI structure/cookie
+
+ @input eFlags :	Flags
+
+ @Return   Pointer to PCI device handle
+
+******************************************************************************/
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+    int err;
+    IMG_UINT32 i;
+    PVR_PCI_DEV *psPVRPCI;
+
+    PVR_TRACE(("OSPCISetDev"));
+
+    if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL,
+        "PCI Device") != PVRSRV_OK)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure"));
+        return IMG_NULL;
+    }
+
+    psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+    psPVRPCI->ePCIFlags = eFlags;
+
+    err = pci_enable_device(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err));
+        return IMG_NULL;
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)	/* PRQA S 3358 */ /* misuse of enums */
+    {
+        pci_set_master(psPVRPCI->psPCIDev);
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)		/* PRQA S 3358 */ /* misuse of enums */
+    {
+#if defined(CONFIG_PCI_MSI)
+        err = pci_enable_msi(psPVRPCI->psPCIDev);
+        if (err != 0)
+        {
+            PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err));
+            psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;	/* PRQA S 1474,3358,4130 */ /* misuse of enums */
+        }
+#else
+        PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
+#endif
+    }
+
+    /* Initialise the PCI resource tracking array */
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+    }
+
+    return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIAcquireDev
+ 
+ @Description 
+ 
+ Acquire a PCI device for subsequent use.
+
+ @input ui16VendorID :	Vendor PCI ID
+
+ @input ui16VendorID :	Device PCI ID
+
+ @input eFlags :	Flags
+
+ @Return   PVESRV_ERROR
+
+******************************************************************************/
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
+{
+    struct pci_dev *psPCIDev;
+
+    psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+    if (psPCIDev == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device"));
+        return IMG_NULL;
+    }
+
+    return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIIRQ
+ 
+ @Description 
+ 
+ Get the interrupt number for the device.
+
+ @input hPVRPCI :	PCI device handle
+
+ @input pui32IRQ :	Pointer to where the interrupt number should be returned
+
+ @Return   PVESRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+    *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+    return PVRSRV_OK;
+}
+
+/* Functions supported by OSPCIAddrRangeFunc */
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+    HOST_PCI_ADDR_RANGE_FUNC_LEN,
+    HOST_PCI_ADDR_RANGE_FUNC_START,
+    HOST_PCI_ADDR_RANGE_FUNC_END,
+    HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+    HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIAddrRangeFunc
+ 
+ @Description 
+ 
+ Internal support function for various address range related functions
+
+ @input eFunc :	Function to perform
+
+ @input hPVRPCI :	PCI device handle
+
+ @input ui32Index :	Address range index
+
+ @Return   function dependent
+
+******************************************************************************/
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+                                     PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+                                     IMG_UINT32 ui32Index)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+    if (ui32Index >= DEVICE_COUNT_RESOURCE)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range"));
+        return 0;
+
+    }
+
+    switch (eFunc)
+    {
+        case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+            return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_START:
+            return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_END:
+            return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+        case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+        {
+            int err;
+
+            err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, PVRSRV_MODNAME);
+            if (err != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err));
+                return 0;
+            }
+            psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+            return 1;
+        }
+        case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+            if (psPVRPCI->abPCIResourceInUse[ui32Index])
+            {
+                pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+                psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+            }
+            return 1;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function"));
+            break;
+    }
+
+    return 0;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIAddrRangeLen
+ 
+ @Description 
+ 
+ Returns length of a given address range length
+
+ @input hPVRPCI :	PCI device handle
+
+ @input ui32Index :	Address range index
+
+ @Return   Length of address range, or 0 if no such range
+
+******************************************************************************/
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index); 
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIAddrRangeStart
+ 
+ @Description 
+ 
+ Returns the start of a given address range
+
+ @input hPVRPCI :	PCI device handle
+
+ @input ui32Index :	Address range index
+
+ @Return   Start of address range, or 0 if no such range
+
+******************************************************************************/
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index); 
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIAddrRangeEnd
+ 
+ @Description 
+ 
+ Returns the end of a given address range
+
+ @input hPVRPCI :	PCI device handle"ayy
+
+ @input ui32Index :	Address range index
+
+ @Return   End of address range, or 0 if no such range
+
+******************************************************************************/
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index); 
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIRequestAddrRange
+ 
+ @Description 
+ 
+ Request a given address range index for subsequent use
+
+ @input hPVRPCI :	PCI device handle
+
+ @input ui32Index :	Address range index
+
+ @Return   PVESRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+                                   IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIReleaseAddrRange
+ 
+ @Description 
+ 
+ Release a given address range that is no longer being used
+
+ @input hPVRPCI :	PCI device handle
+
+ @input ui32Index :	Address range index
+
+ @Return   PVESRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+    return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIReleaseDev
+ 
+ @Description 
+ 
+ Release a PCI device that is no longer being used
+
+ @input hPVRPCI :	PCI device handle
+
+ @Return   PVESRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int i;
+
+    PVR_TRACE(("OSPCIReleaseDev"));
+
+    /* Release all PCI regions that are currently in use */
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
+            pci_release_region(psPVRPCI->psPCIDev, i);
+            psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+        }
+    }
+
+#if defined(CONFIG_PCI_MSI)
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)		/* PRQA S 3358 */ /* misuse of enums */
+    {
+        pci_disable_msi(psPVRPCI->psPCIDev);
+    }
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)	/* PRQA S 3358 */ /* misuse of enums */
+    {
+        pci_clear_master(psPVRPCI->psPCIDev);
+    }
+#endif
+    pci_disable_device(psPVRPCI->psPCIDev);
+
+    OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
+	/*not nulling pointer, copy on stack*/
+
+    return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCISuspendDev
+ 
+ @Description 
+ 
+ Prepare PCI device to be turned off by power management
+
+ @input hPVRPCI :	PCI device handle
+
+ @Return   PVESRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int i;
+    int err;
+
+    PVR_TRACE(("OSPCISuspendDev"));
+
+    /* Release all PCI regions that are currently in use */
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            pci_release_region(psPVRPCI->psPCIDev, i);
+        }
+    }
+
+    err = pci_save_state(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err));
+        return PVRSRV_ERROR_PCI_CALL_FAILED;
+    }
+
+    pci_disable_device(psPVRPCI->psPCIDev);
+
+    err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+    switch(err)
+    {
+        case 0:
+            break;
+        case -EIO:
+            PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM"));
+            break;
+        case -EINVAL:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state"));
+            break;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err));
+            break;
+    }
+
+    return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSPCIResumeDev
+ 
+ @Description 
+ 
+ Prepare a PCI device to be resumed by power management
+
+ @input hPVRPCI :	PCI device handle
+
+ @input pvPCICookie :	Pointer to OS specific PCI structure/cookie
+
+ @input eFlags :	Flags
+
+ @Return   PVESRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+    PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+    int err;
+    int i;
+
+    PVR_TRACE(("OSPCIResumeDev"));
+
+    err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+    switch(err)
+    {
+        case 0:
+            break;
+        case -EIO:
+            PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM"));
+            break;
+        case -EINVAL:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state"));
+            return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+        default:
+            PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err));
+            return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+    }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+    pci_restore_state(psPVRPCI->psPCIDev);
+#else
+    err = pci_restore_state(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_restore_state failed (%d)", err));
+        return PVRSRV_ERROR_PCI_CALL_FAILED;
+    }
+#endif
+
+    err = pci_enable_device(psPVRPCI->psPCIDev);
+    if (err != 0)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err));
+        return PVRSRV_ERROR_PCI_CALL_FAILED;
+    }
+
+    if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)	/* PRQA S 3358 */ /* misuse of enums */
+        pci_set_master(psPVRPCI->psPCIDev);
+
+    /* Restore the PCI resource tracking array */
+    for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+    {
+        if (psPVRPCI->abPCIResourceInUse[i])
+        {
+            err = pci_request_region(psPVRPCI->psPCIDev, i, PVRSRV_MODNAME);
+            if (err != 0)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err));
+            }
+        }
+
+    }
+
+    return PVRSRV_OK;
+}
+
+#endif /* #if defined(CONFIG_PCI) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) */
+
+#define	OS_MAX_TIMERS	8
+
+/* Timer callback strucure used by OSAddTimer */
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+    IMG_BOOL			bInUse;
+    PFN_TIMER_FUNC		pfnTimerFunc;
+    IMG_VOID 			*pvData;	
+    struct timer_list		sTimer;
+    IMG_UINT32			ui32Delay;
+    IMG_BOOL			bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    struct work_struct		sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct	*psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to sTimers */
+/* PRQA S 0671,0685 1 */ /* C99 macro not understood by QAC */
+static spinlock_t sTimerStructLock = SPIN_LOCK_UNLOCKED;
+#else
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{
+    if (!psTimerCBData->bActive)
+        return;
+
+    /* call timer callback */
+    psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+    
+    /* reset timer */
+    mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	OSTimerCallbackWrapper
+ 
+ @Description 
+ 
+ OS specific timer callback wrapper function
+ 
+ @Input    ui32Data : timer callback data
+
+ @Return   NONE
+
+******************************************************************************/
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINTPTR_T uiData)
+{
+    TIMER_CALLBACK_DATA	*psTimerCBData = (TIMER_CALLBACK_DATA*)uiData;
+    
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    int res;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+#else
+    res = schedule_work(&psTimerCBData->sWork);
+#endif
+    if (res == 0)
+    {
+        PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));		
+    }
+#else
+    OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+    OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+/*!
+******************************************************************************
+
+ @Function	OSAddTimer
+ 
+ @Description 
+ 
+ OS specific function to install a timer callback
+ 
+ @Input    pfnTimerFunc : timer callback
+
+ @Input    *pvData :callback data
+ 
+ @Input		ui32MsTimeout: callback period 
+
+ @Return   IMG_HANDLE  : valid handle success, NULL failure
+
+******************************************************************************/
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
+{
+    TIMER_CALLBACK_DATA	*psTimerCBData;
+    IMG_UINTPTR_T		ui;
+#if !(defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE))
+    unsigned long		ulLockFlags;
+#endif
+
+    /* check callback */
+    if(!pfnTimerFunc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));		
+        return IMG_NULL;		
+    }
+    
+    /* Allocate timer callback data structure */
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    mutex_lock(&sTimerStructLock);
+#else
+    spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+    for (ui = 0; ui < OS_MAX_TIMERS; ui++)
+    {
+        psTimerCBData = &sTimers[ui];
+        if (!psTimerCBData->bInUse)
+        {
+            psTimerCBData->bInUse = IMG_TRUE;
+            break;
+        }
+    }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    mutex_unlock(&sTimerStructLock);
+#else
+    spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+    if (ui >= OS_MAX_TIMERS)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));		
+        return IMG_NULL;	
+    }
+
+    psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+    psTimerCBData->pvData = pvData;
+    psTimerCBData->bActive = IMG_FALSE;
+    
+    /*
+        HZ = ticks per second
+        ui32MsTimeout = required ms delay
+        ticks = (Hz * ui32MsTimeout) / 1000	
+    */
+    psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+                                ?	1
+                                :	((HZ * ui32MsTimeout) / 1000);
+    /* initialise object */
+    init_timer(&psTimerCBData->sTimer);
+    
+    /* setup timer object */
+    /* PRQA S 0307,0563 1 */ /* ignore warning about inconpartible ptr casting */
+    psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
+    psTimerCBData->sTimer.data = (IMG_UINTPTR_T)psTimerCBData;
+    
+    return (IMG_HANDLE)(ui + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+    IMG_UINTPTR_T ui = ((IMG_UINTPTR_T)hTimer) - 1;
+
+    PVR_ASSERT(ui < OS_MAX_TIMERS);
+
+    return &sTimers[ui];
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSRemoveTimer
+ 
+ @Description 
+ 
+ OS specific function to remove a timer callback
+ 
+ @Input    hTimer : timer handle
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(!psTimerCBData->bActive);
+
+    /* free timer callback data struct */
+    psTimerCBData->bInUse = IMG_FALSE;
+    
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	OSEnableTimer
+ 
+ @Description 
+ 
+ OS specific function to enable a timer callback
+ 
+ @Input    hTimer : timer handle
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(!psTimerCBData->bActive);
+
+    /* Start timer arming */
+    psTimerCBData->bActive = IMG_TRUE;
+
+    /* set the expire time */
+    psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+    /* Add the timer to the list */
+    add_timer(&psTimerCBData->sTimer);
+    
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	OSDisableTimer
+ 
+ @Description 
+ 
+ OS specific function to disable a timer callback
+ 
+ @Input    hTimer : timer handle
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+    TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+    PVR_ASSERT(psTimerCBData->bInUse);
+    PVR_ASSERT(psTimerCBData->bActive);
+
+    /* Stop timer from arming */
+    psTimerCBData->bActive = IMG_FALSE;
+    smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    flush_scheduled_work();
+#endif
+
+    /* remove timer */
+    del_timer_sync(&psTimerCBData->sTimer);	
+    
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    /*
+     * This second flush is to catch the case where the timer ran
+     * before we managed to delete it, in which case, it will have
+     * queued more work for the workqueue.  Since the bActive flag
+     * has been cleared, this second flush won't result in the
+     * timer being rearmed.
+     */
+    flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    flush_scheduled_work();
+#endif
+
+    return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	OSEventObjectCreateKM
+ 
+ @Description 
+ 
+ OS specific function to create an event object
+ 
+ @Input    pszName : Globally unique event object name (if null name must be autogenerated)
+ 
+ @Output   psEventObject : OS event object info structure
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
+{
+
+    PVRSRV_ERROR eError = PVRSRV_OK;
+    
+    if(psEventObject)
+    {
+        if(pszName)
+        {
+            /* copy over the event object name */
+            strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
+        }
+        else
+        {
+            /* autogenerate a name */	
+            static IMG_UINT16 ui16NameIndex = 0;			
+            snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+        }
+        
+        if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
+        {
+             eError = PVRSRV_ERROR_OUT_OF_MEMORY;	
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreateKM: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;	
+    }
+    
+    return eError;
+
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	OSEventObjectDestroyKM
+ 
+ @Description 
+ 
+ OS specific function to destroy an event object
+ 
+ @Input    psEventObject : OS event object info structure
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT *psEventObject)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(psEventObject->hOSEventKM)
+        {
+            LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+        }
+        else
+        {
+            PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: hOSEventKM is not a valid pointer"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSEventObjectWaitKM
+ 
+ @Description 
+ 
+ OS specific function to wait for an event object.  Called from client
+ 
+ @Input    hOSEventKM : OS and kernel specific handle to event object
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError;
+    
+    if(hOSEventKM)
+    {
+        eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWaitKM: hOSEventKM is not a valid handle"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSEventObjectOpenKM
+ 
+ @Description 
+ 
+ OS specific function to open an event object.  Called from client
+ 
+ @Input    psEventObject : Pointer to an event object
+ @Output   phOSEvent : OS and kernel specific handle to event object
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
+                                            IMG_HANDLE *phOSEvent)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+    
+    if(psEventObject)
+    {
+        if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreateKM: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSEventObjectCloseKM
+ 
+ @Description 
+ 
+ OS specific function to close an event object.  Called from client
+ 
+ @Input    psEventObject : Pointer to an event object
+ @OInput   hOSEventKM : OS and kernel specific handle to event object
+
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
+                                            IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError = PVRSRV_OK;
+
+    if(psEventObject)
+    {
+        if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+            eError = PVRSRV_ERROR_INVALID_PARAMS;
+        }
+
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroyKM: psEventObject is not a valid pointer"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+    
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSEventObjectSignalKM
+ 
+ @Description 
+ 
+ OS specific function to 'signal' an event object.  Called from L/MISR
+ 
+ @Input    hOSEventKM : OS and kernel specific handle to event object
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM)
+{
+    PVRSRV_ERROR eError;
+    
+    if(hOSEventKM)
+    {
+        eError = LinuxEventObjectSignal(hOSEventKM);
+    }
+    else
+    {
+        PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignalKM: hOSEventKM is not a valid handle"));
+        eError = PVRSRV_ERROR_INVALID_PARAMS;
+    }
+    
+    return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSProcHasPrivSrvInit
+ 
+ @Description 
+ 
+ Does the process have sufficient privileges to initialise services?
+ 
+ @Input    none
+
+ @Return   IMG_BOOL :
+
+******************************************************************************/
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
+{
+    return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSCopyToUser
+ 
+ @Description 
+ 
+ Copy a block of data into user space
+ 
+ @Input    pvSrc
+ 
+ @Output    pvDest
+
+ @Input 	ui32Bytes 
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, 
+                          IMG_VOID *pvDest, 
+                          IMG_VOID *pvSrc, 
+                          IMG_SIZE_T uiBytes)
+{
+    PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+    if(pvr_copy_to_user(pvDest, pvSrc, uiBytes)==0)
+        return PVRSRV_OK;
+    else
+        return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSCopyFromUser
+ 
+ @Description 
+ 
+ Copy a block of data from the user space
+ 
+ @Output    pvDest
+ 
+ @Input    pvSrc
+
+ @Input 	ui32Bytes 
+
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess, 
+                             IMG_VOID *pvDest, 
+                             IMG_VOID *pvSrc, 
+                             IMG_SIZE_T uiBytes)
+{
+    PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+    if(pvr_copy_from_user(pvDest, pvSrc, uiBytes)==0)
+        return PVRSRV_OK;
+    else
+        return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSAccessOK
+ 
+ @Description 
+ 
+ Checks if a user space pointer is valide
+ 
+ @Input    eVerification
+
+ @Input    pvUserPtr
+
+ @Input 	ui32Bytes 
+
+ @Return   IMG_BOOL :
+
+******************************************************************************/
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T uiBytes)
+{
+    IMG_INT linuxType;
+
+    if (eVerification == PVR_VERIFY_READ)
+    {
+        linuxType = VERIFY_READ;
+    }
+    else
+    {
+        PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+        linuxType = VERIFY_WRITE;
+    }
+
+    return access_ok(linuxType, pvUserPtr, uiBytes);
+}
+
+typedef enum _eWrapMemType_
+{
+    WRAP_TYPE_NULL = 0,
+    WRAP_TYPE_GET_USER_PAGES,
+    WRAP_TYPE_FIND_VMA
+} eWrapMemType;
+
+typedef struct _sWrapMemInfo_
+{
+    eWrapMemType eType;
+    IMG_INT iNumPages;
+    IMG_INT iNumPagesMapped;
+    struct page **ppsPages;
+    IMG_SYS_PHYADDR *psPhysAddr;
+    IMG_INT iPageOffset;
+#if defined(DEBUG)
+    IMG_UINTPTR_T uStartAddr;
+    IMG_UINTPTR_T uBeyondEndAddr;
+    struct vm_area_struct *psVMArea;
+#endif
+} sWrapMemInfo;
+
+
+/*!
+******************************************************************************
+
+ @Function	*CPUVAddrToPFN
+ 
+ @Description 
+ 
+ Find the PFN associated with a given CPU virtual address, and return
+ the associated page structure, if it exists.
+ The page in question must be present (i.e. no fault handling required),
+ and must be writable.  A get_page is done on the returned page structure.
+ 
+ @Input    psVMArea - pointer to VM area structure
+       uCPUVAddr - CPU virtual address
+       pui32PFN - Pointer to returned PFN.
+       ppsPAge - Pointer to returned page structure pointer.
+
+ @Output   *pui32PFN - Set to PFN
+ 	   *ppsPage - Pointer to the page structure if present, else NULL.
+ @Return   IMG_TRUE if PFN lookup was succesful.
+
+******************************************************************************/
+static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINTPTR_T uCPUVAddr, IMG_UINT32 *pui32PFN, struct page **ppsPage)
+{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
+    pgd_t *psPGD;
+    pud_t *psPUD;
+    pmd_t *psPMD;
+    pte_t *psPTE;
+    struct mm_struct *psMM = psVMArea->vm_mm;
+    spinlock_t *psPTLock;
+    IMG_BOOL bRet = IMG_FALSE;
+
+    *pui32PFN = 0;
+    *ppsPage = NULL;
+
+    psPGD = pgd_offset(psMM, uCPUVAddr);
+    if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+        return bRet;
+
+    psPUD = pud_offset(psPGD, uCPUVAddr);
+    if (pud_none(*psPUD) || pud_bad(*psPUD))
+        return bRet;
+
+    psPMD = pmd_offset(psPUD, uCPUVAddr);
+    if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+        return bRet;
+
+    psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, uCPUVAddr, &psPTLock);
+
+    if ((pte_none(*psPTE) == 0) && (pte_present(*psPTE) != 0) && (pte_write(*psPTE) != 0))
+    {
+        *pui32PFN = pte_pfn(*psPTE);
+	bRet = IMG_TRUE;
+
+        if (pfn_valid(*pui32PFN))
+        {
+            *ppsPage = pfn_to_page(*pui32PFN);
+
+            get_page(*ppsPage);
+        }
+    }
+
+    pte_unmap_unlock(psPTE, psPTLock);
+
+    return bRet;
+#else
+    return IMG_FALSE;
+#endif
+}
+
+/*!
+******************************************************************************
+
+ @Function	OSReleasePhysPageAddr
+ 
+ @Description 
+ 
+ Release wrapped memory.
+
+ @Input    hOSWrapMem : Driver cookie
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+    sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
+    IMG_INT i;
+
+    if (psInfo == IMG_NULL)
+    {
+        PVR_DPF((PVR_DBG_WARNING,
+            "OSReleasePhysPageAddr: called with null wrap handle"));
+	return PVRSRV_OK;
+    }
+
+    switch (psInfo->eType)
+    {
+	case WRAP_TYPE_NULL:
+	{
+            PVR_DPF((PVR_DBG_WARNING,
+                "OSReleasePhysPageAddr: called with wrap type WRAP_TYPE_NULL"));
+	    break;
+	}
+        case WRAP_TYPE_GET_USER_PAGES:
+        {
+            for (i = 0; i < psInfo->iNumPagesMapped; i++)
+            {
+                struct page *psPage = psInfo->ppsPages[i];
+
+		PVR_ASSERT(psPage != NULL);
+
+                /*
+		 * If the number of pages mapped is not the same as
+		 * the number of pages in the address range, then
+		 * get_user_pages must have failed, so we are cleaning
+		 * up after failure, and the pages can't be dirty.
+	 	 */
+		if (psInfo->iNumPagesMapped == psInfo->iNumPages)
+		{
+                    if (!PageReserved(psPage))
+                    {
+                        SetPageDirty(psPage);
+                    }
+	        }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0))
+                page_cache_release(psPage);
+#else
+                put_page(psPage);
+#endif
+	    }
+            break;
+        }
+        case WRAP_TYPE_FIND_VMA:
+        {
+            for (i = 0; i < psInfo->iNumPages; i++)
+            {
+		if (psInfo->ppsPages[i] != IMG_NULL)
+		{
+                    put_page(psInfo->ppsPages[i]);
+		}
+            }
+            break;
+        }
+        default:
+        {
+            PVR_DPF((PVR_DBG_ERROR,
+                "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType));
+            return PVRSRV_ERROR_INVALID_WRAP_TYPE;
+        }
+    }
+
+    if (psInfo->ppsPages != IMG_NULL)
+    {
+        kfree(psInfo->ppsPages);
+    }
+
+    if (psInfo->psPhysAddr != IMG_NULL)
+    {
+        kfree(psInfo->psPhysAddr);
+    }
+
+    kfree(psInfo);
+
+    return PVRSRV_OK;
+}
+
+#if defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER)
+
+static IMG_UINT32 CPUAddrToTilerPhy(IMG_UINT32 uiAddr)
+{
+	IMG_UINT32 ui32PhysAddr = 0;
+	pte_t *ptep, pte;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pud_t *pud;
+
+	pgd = pgd_offset(current->mm, uiAddr);
+	if (pgd_none(*pgd) || pgd_bad(*pgd))
+		goto err_out;
+
+	pud = pud_offset(pgd, uiAddr);
+	if (pud_none(*pud) || pud_bad(*pud))
+		goto err_out;
+
+	pmd = pmd_offset(pud, uiAddr);
+	if (pmd_none(*pmd) || pmd_bad(*pmd))
+		goto err_out;
+
+	ptep = pte_offset_map(pmd, uiAddr);
+	if (!ptep)
+		goto err_out;
+
+	pte = *ptep;
+	if (!pte_present(pte))
+		goto err_out;
+
+	ui32PhysAddr = (pte & PAGE_MASK) | (~PAGE_MASK & uiAddr);
+
+	/* If the physAddr is not in the TILER physical range
+	 * then we don't proceed.
+	 */
+	if (ui32PhysAddr < 0x60000000 && ui32PhysAddr > 0x7fffffff)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "CPUAddrToTilerPhy: Not in tiler range"));
+		ui32PhysAddr = 0;
+		goto err_out;
+	}
+
+err_out:
+	return ui32PhysAddr;
+}
+
+#endif /* defined(CONFIG_TI_TILER) && defined(CONFIG_DRM_OMAP_DMM_TILER) */
+
+/*!
+******************************************************************************
+
+ @Function	OSAcquirePhysPageAddr
+ 
+ @Description 
+ 
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr, 
+                                    IMG_SIZE_T uiBytes, 
+                                    IMG_SYS_PHYADDR *psSysPAddr,
+                                    IMG_HANDLE *phOSWrapMem)
+{
+    IMG_UINTPTR_T uStartAddrOrig = (IMG_UINTPTR_T) pvCPUVAddr;
+    IMG_SIZE_T uAddrRangeOrig = uiBytes;
+    IMG_UINTPTR_T uBeyondEndAddrOrig = uStartAddrOrig + uAddrRangeOrig;
+    IMG_UINTPTR_T uStartAddr;
+    IMG_SIZE_T uAddrRange;
+    IMG_UINTPTR_T uBeyondEndAddr;
+    IMG_UINTPTR_T uAddr;
+    IMG_INT i;
+    struct vm_area_struct *psVMArea;
+    sWrapMemInfo *psInfo = NULL;
+    IMG_BOOL bHavePageStructs = IMG_FALSE;
+    IMG_BOOL bHaveNoPageStructs = IMG_FALSE;
+    IMG_BOOL bMMapSemHeld = IMG_FALSE;
+    PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+    /* Align start and end addresses to page boundaries */
+    uStartAddr = uStartAddrOrig & PAGE_MASK;
+    uBeyondEndAddr = PAGE_ALIGN(uBeyondEndAddrOrig);
+    uAddrRange = uBeyondEndAddr - uStartAddr;
+
+    /*
+     * Check for address range calculation overflow, and attempts to wrap
+     * zero bytes.
+     */
+    if (uBeyondEndAddr <= uStartAddr)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Invalid address range (start " UINTPTR_FMT  ", length %" SIZE_T_FMT_LEN "x)",
+		uStartAddrOrig, uAddrRangeOrig));
+        goto error;
+    }
+
+    /* Allocate information structure */
+    psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+    if (psInfo == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate information structure"));
+        goto error;
+    }
+    memset(psInfo, 0, sizeof(*psInfo));
+
+#if defined(DEBUG)
+    psInfo->uStartAddr = uStartAddrOrig;
+    psInfo->uBeyondEndAddr = uBeyondEndAddrOrig;
+#endif
+
+    psInfo->iNumPages = (IMG_INT)(uAddrRange >> PAGE_SHIFT);
+    psInfo->iPageOffset = (IMG_INT)(uStartAddrOrig & ~PAGE_MASK);
+
+    /* Allocate physical address array */
+    psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
+    if (psInfo->psPhysAddr == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate page array"));		
+        goto error;
+    }
+    memset(psInfo->psPhysAddr, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr));
+
+    /* Allocate page array */
+    psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages),  GFP_KERNEL);
+    if (psInfo->ppsPages == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't allocate page array"));		
+        goto error;
+    }
+    memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+    /* Default error code from now on */
+    eError = PVRSRV_ERROR_BAD_MAPPING;
+
+    /* Set the mapping type to aid clean up */
+    psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+    /* Lock down user memory */
+    down_read(&current->mm->mmap_sem);
+    bMMapSemHeld = IMG_TRUE;
+
+    /* Get page list */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0))
+    psInfo->iNumPagesMapped = get_user_pages(
+		current, current->mm,
+		uStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+#else
+    psInfo->iNumPagesMapped = get_user_pages_remote(
+		current, current->mm,
+		uStartAddr, psInfo->iNumPages, FOLL_WRITE, psInfo->ppsPages, NULL, NULL);
+#endif
+    if (psInfo->iNumPagesMapped >= 0)
+    {
+        /* See if we got all the pages we wanted */
+        if (psInfo->iNumPagesMapped != psInfo->iNumPages)
+        {
+            PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, psInfo->iNumPagesMapped));
+
+            goto error;
+        }
+
+        /* Build list of physical page addresses */
+        for (i = 0; i < psInfo->iNumPages; i++)
+        {
+            IMG_CPU_PHYADDR CPUPhysAddr;
+			IMG_UINT32 ui32PFN;
+
+            ui32PFN = page_to_pfn(psInfo->ppsPages[i]);
+            CPUPhysAddr.uiAddr = ui32PFN << PAGE_SHIFT;
+	    if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ui32PFN)
+	    {
+                PVR_DPF((PVR_DBG_ERROR,
+		    "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ui32PFN));
+
+		    goto error;
+	    }
+            psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+            psSysPAddr[i] = psInfo->psPhysAddr[i];
+            
+        }
+
+        goto exit;
+    }
+
+    PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), using CPU page table", psInfo->iNumPagesMapped));
+    
+    /* Reset some fields */
+    psInfo->eType = WRAP_TYPE_NULL;
+    psInfo->iNumPagesMapped = 0;
+    memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+    /*
+     * get_user_pages didn't work.  If this is due to the address range
+     * representing memory mapped I/O, then we'll look for the pages
+     * in the appropriate memory region of the process.
+     */
+
+    /* Set the mapping type to aid clean up */
+    psInfo->eType = WRAP_TYPE_FIND_VMA;
+
+    psVMArea = find_vma(current->mm, uStartAddrOrig);
+    if (psVMArea == NULL)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Couldn't find memory region containing start address " UINTPTR_FMT, 
+            uStartAddrOrig));
+        
+        goto error;
+    }
+#if defined(DEBUG)
+    psInfo->psVMArea = psVMArea;
+#endif
+
+    /*
+     * find_vma locates a region with an end point past a given
+     * virtual address.  So check the address is actually in the region.
+     */
+    if (uStartAddrOrig < psVMArea->vm_start)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Start address " UINTPTR_FMT " is outside of the region returned by find_vma", 
+            uStartAddrOrig));
+        goto error;
+    }
+
+    /* Now check the end address is in range */
+    if (uBeyondEndAddrOrig > psVMArea->vm_end)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: End address " UINTPTR_FMT " is outside of the region returned by find_vma", uBeyondEndAddrOrig));
+        goto error;
+    }
+
+    /* Does the region represent memory mapped I/O? */
+    if (!(psVMArea->vm_flags & VM_IO))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
+        goto error;
+    }
+
+    /* We require read and write access */
+    if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags));
+        goto error;
+    }
+
+    for (uAddr = uStartAddrOrig, i = 0; uAddr < uBeyondEndAddrOrig; uAddr += PAGE_SIZE, i++)
+    {
+	IMG_CPU_PHYADDR CPUPhysAddr;
+	IMG_UINT32 ui32PFN = 0;
+
+	PVR_ASSERT(i < psInfo->iNumPages);
+
+	if (!CPUVAddrToPFN(psVMArea, uAddr, &ui32PFN, &psInfo->ppsPages[i]))
+	{
+            PVR_DPF((PVR_DBG_ERROR,
+	       "OSAcquirePhysPageAddr: Invalid CPU virtual address"));
+
+	    goto error;
+	}
+	if (psInfo->ppsPages[i] == NULL)
+	{
+#if defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER)
+		/* This could be tiler memory.*/
+		IMG_UINT32 ui32TilerAddr = CPUAddrToTilerPhy(uAddr);
+		if (ui32TilerAddr)
+		{
+			bHavePageStructs = IMG_TRUE;
+			psInfo->iNumPagesMapped++;
+			psInfo->psPhysAddr[i].uiAddr = ui32TilerAddr;
+			psSysPAddr[i].uiAddr = ui32TilerAddr;
+			continue;
+		}
+#endif /* defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER) */
+
+	    bHaveNoPageStructs = IMG_TRUE;
+	}
+	else
+	{
+	    bHavePageStructs = IMG_TRUE;
+
+	    psInfo->iNumPagesMapped++;
+
+	    PVR_ASSERT(ui32PFN == page_to_pfn(psInfo->ppsPages[i]));
+	}
+
+        CPUPhysAddr.uiAddr = ui32PFN << PAGE_SHIFT;
+	if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ui32PFN)
+	{
+                PVR_DPF((PVR_DBG_ERROR,
+		    "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ui32PFN));
+
+		    goto error;
+	}
+
+	psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+	psSysPAddr[i] = psInfo->psPhysAddr[i];
+    }
+    PVR_ASSERT(i ==  psInfo->iNumPages);
+
+#if defined(VM_MIXEDMAP)
+    if ((psVMArea->vm_flags & VM_MIXEDMAP) != 0)
+    {
+        goto exit;
+    }
+#endif
+
+    if (bHavePageStructs && bHaveNoPageStructs)
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Region is VM_MIXEDMAP, but isn't marked as such"));
+	goto error;
+    }
+
+    if (!bHaveNoPageStructs)
+    {
+	/* The ideal case; every page has a page structure */
+	goto exit;
+    }
+
+#if defined(VM_PFNMAP)
+    if ((psVMArea->vm_flags & VM_PFNMAP) == 0)
+#endif
+    {
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Region is VM_PFNMAP, but isn't marked as such"));
+	goto error;
+    }
+
+exit:
+    PVR_ASSERT(bMMapSemHeld);
+    up_read(&current->mm->mmap_sem);
+    bMMapSemHeld = IMG_FALSE;
+
+    PVR_ASSERT(psInfo->eType != 0);
+
+    if (bHaveNoPageStructs)
+    {
+#if defined(PVR_ALLOW_NON_PAGE_STRUCT_MEMORY_IMPORT)
+	/*
+	 * Allowing the GPU to access pages that can't be locked down is
+	 * potentially unsafe. For recent versions of Linux, there are
+	 * safer ways to get access to such memory, such as DMA Buffer
+	 * sharing (DMABUF).
+	 */
+        PVR_DPF((PVR_DBG_MESSAGE,
+            "OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)"));
+#else
+        PVR_DPF((PVR_DBG_ERROR,
+            "OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)"));
+	goto error;
+#endif
+    }
+
+    /* Return the cookie */
+    *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+    return PVRSRV_OK;
+
+error:
+    if (bMMapSemHeld)
+    {
+        up_read(&current->mm->mmap_sem);
+    }
+    OSReleasePhysPageAddr((IMG_HANDLE)psInfo);
+
+    PVR_ASSERT(eError != PVRSRV_OK);
+
+    return eError;
+}
+
+#if ! (defined(__arm__) || defined(__aarch64__))
+# define USE_VIRTUAL_CACHE_OP
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+# define USE_VIRTUAL_CACHE_OP
+# if defined(CONFIG_OUTER_CACHE)
+#  define USE_PHYSICAL_CACHE_OP
+# endif
+#else
+# define USE_PHYSICAL_CACHE_OP
+#endif
+
+extern PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+/* g_sMMapMutex must be held while this function is called */
+static
+IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
+							IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
+{
+	PKV_OFFSET_STRUCT psOffsetStruct;
+	IMG_VOID *pvMinVAddr;
+
+	/* There's no kernel-virtual for this type of allocation, so if
+	 * we're flushing it, it must be user-virtual, and therefore
+	 * have a mapping.
+	 */
+	list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
+	{
+		if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
+			continue;
+
+		pvMinVAddr = (IMG_VOID *)psOffsetStruct->uiUserVAddr;
+
+		/* Within permissible range */
+		if(pvRangeAddrStart >= pvMinVAddr &&
+		   ui32Length <= psOffsetStruct->uiRealByteSize)
+			return pvMinVAddr;
+	}
+
+	return IMG_NULL;
+}
+
+#if defined(USE_PHYSICAL_CACHE_OP)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+typedef void (*PhysicalCacheOp_t)(phys_addr_t uStart, phys_addr_t uEnd);
+#else
+typedef void (*PhysicalCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+#endif
+
+/* 
+	Note: use IMG_CPU_PHYADDR to return CPU Phys Addresses, and not just 'unsigned long',
+	as this is not big enough to hold physical addresses on 32-bit PAE devices.
+*/
+typedef IMG_BOOL (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
+                                    IMG_VOID *pvRangeAddrStart,
+                                    IMG_UINT32 ui32PageNumOffset,
+                                    IMG_UINT32 ui32PageNum,
+                                    IMG_CPU_PHYADDR *psStart);
+
+static IMG_BOOL VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
+                                  IMG_VOID *pvRangeAddrStart,
+                                  IMG_UINT32 ui32PageNumOffset,
+                                  IMG_UINT32 ui32PageNum,
+                                  IMG_CPU_PHYADDR *psStart)
+{
+	psStart->uiAddr = vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+	return IMG_TRUE;
+}
+
+static IMG_BOOL ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
+                                     IMG_VOID *pvRangeAddrStart,
+                                     IMG_UINT32 ui32PageNumOffset,
+                                     IMG_UINT32 ui32PageNum,
+                                     IMG_CPU_PHYADDR *psStart)
+{
+	IMG_SYS_PHYADDR SysPAddr;
+	SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum];
+	*psStart = SysSysPAddrToCpuPAddr(SysPAddr);
+	return IMG_TRUE;
+}
+
+static IMG_BOOL AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
+                                     IMG_VOID *pvRangeAddrStart,
+                                     IMG_UINT32 ui32PageNumOffset,
+                                     IMG_UINT32 ui32PageNum,
+                                     IMG_CPU_PHYADDR *psStart)
+{
+	struct page *pPage;
+
+	pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageNumOffset + ui32PageNum];
+	psStart->uiAddr = page_to_pfn(pPage) << PAGE_SHIFT;
+	return IMG_TRUE;
+}
+
+static IMG_BOOL AllocPagesSparseAreaToPhys(LinuxMemArea *psLinuxMemArea,
+                                           IMG_VOID *pvRangeAddrStart,
+                                           IMG_UINT32 ui32PageNumOffset,
+                                           IMG_UINT32 ui32PageNum,
+                                           IMG_CPU_PHYADDR *psStart)
+{
+	IMG_UINT32 ui32VirtOffset = (ui32PageNumOffset + ui32PageNum) << PAGE_SHIFT;
+	IMG_UINT32 ui32PhysOffset;
+	struct page *pPage;
+
+	if (BM_VirtOffsetToPhysical(psLinuxMemArea->hBMHandle, ui32VirtOffset, &ui32PhysOffset))
+	{
+		PVR_ASSERT(ui32PhysOffset <= ui32VirtOffset);
+		pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PhysOffset >> PAGE_SHIFT];
+		psStart->uiAddr = page_to_pfn(pPage) << PAGE_SHIFT;
+		return IMG_TRUE;
+	}
+
+	return IMG_FALSE;
+}
+
+static inline void DoPhysicalCacheOp(LinuxMemArea *psLinuxMemArea,
+                                     IMG_VOID *pvRangeAddrStart,
+                                     IMG_SIZE_T uiLength,
+                                     IMG_UINTPTR_T uPageNumOffset,
+                                     MemAreaToPhys_t pfnMemAreaToPhys,
+                                     PhysicalCacheOp_t pfnPhysicalCacheOp)
+{
+	IMG_CPU_PHYADDR sStart, sEnd;
+	unsigned long ulLength, ulStartOffset, ulEndOffset;
+	IMG_UINT32 i, ui32NumPages;
+	IMG_BOOL bValidPage;
+
+	/* Length and offsets of flush region WRT page alignment */
+	ulLength = (unsigned long)uiLength;
+	ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
+	ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
+
+	/* The affected pages, rounded up */
+	ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	for(i = 0; i < ui32NumPages; i++)
+	{
+		bValidPage = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
+					      uPageNumOffset, i, &sStart);
+		if (bValidPage)
+		{
+			sEnd.uiAddr = sStart.uiAddr + PAGE_SIZE;
+
+			if(i == ui32NumPages - 1 && ulEndOffset != 0)
+				sEnd.uiAddr = sStart.uiAddr + ulEndOffset;
+
+			if(i == 0)
+				sStart.uiAddr += ulStartOffset;
+
+			pfnPhysicalCacheOp(sStart.uiAddr, sEnd.uiAddr);
+		}
+	}
+}
+
+#endif /* defined(USE_PHYSICAL_CACHE_OP) */
+
+#if defined(USE_VIRTUAL_CACHE_OP)
+typedef void (*VirtualCacheOp_t)(const void *pvStart, const void *pvEnd);
+
+static inline void DoVirtualCacheOp(IMG_HANDLE hOSMemHandle,
+                                    IMG_UINT32 ui32ByteOffset,
+                                    IMG_VOID *pvRangeAddrStart,
+                                    IMG_UINT32 ui32Length,
+                                    VirtualCacheOp_t pfnVirtualCacheOp)
+{
+	LinuxMemArea *psLinuxMemArea = hOSMemHandle;
+
+	if (!psLinuxMemArea->hBMHandle)
+	{
+		pfnVirtualCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+	}
+	else
+	{
+		IMG_UINT32 ui32ByteRemain = ui32Length;
+		IMG_UINT32 ui32BytesToDo = PAGE_SIZE - (((IMG_UINTPTR_T) pvRangeAddrStart) & (~PAGE_MASK));
+		IMG_UINT8 *pbDo = (IMG_UINT8 *) pvRangeAddrStart;
+	
+		while(ui32ByteRemain)
+		{
+			if (BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32ByteOffset + (ui32Length - ui32ByteRemain)))
+			{
+				pfnVirtualCacheOp(pbDo, pbDo + ui32BytesToDo);
+			}
+			pbDo += ui32BytesToDo;
+			ui32ByteRemain -= ui32BytesToDo;
+			ui32BytesToDo = MIN(ui32ByteRemain, PAGE_SIZE);
+		}
+	}
+}
+#endif /* defined(USE_VIRTUAL_CACHE_OP) */
+
+static
+IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
+                             IMG_UINT32 ui32ByteOffset,
+                             IMG_VOID *pvVirtRangeStart,
+                             IMG_SIZE_T uiLength
+#if defined(USE_VIRTUAL_CACHE_OP)
+                             , VirtualCacheOp_t pfnVirtualCacheOp
+#endif
+#if defined(USE_PHYSICAL_CACHE_OP)
+                             , PhysicalCacheOp_t pfnPhysicalCacheOp
+#endif
+                             )
+{
+	LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+	IMG_UINTPTR_T uiAreaOffset = 0;
+	struct list_head *psMMapOffsetStructList;
+	IMG_VOID *pvMinVAddr;
+#if defined(USE_PHYSICAL_CACHE_OP)
+	MemAreaToPhys_t pfnMemAreaToPhys = IMG_NULL;
+	IMG_UINTPTR_T uPageNumOffset = 0;
+	IMG_VOID *pvPhysRangeStart = pvVirtRangeStart;
+#endif
+
+	PVR_ASSERT(psLinuxMemArea != IMG_NULL);
+
+	LinuxLockMutexNested(&g_sMMapMutex, PVRSRV_LOCK_CLASS_MMAP);
+
+	psMMapOffsetStructList = &psLinuxMemArea->sMMapOffsetStructList;
+
+	/*
+		Don't check the length in the case of sparse mappings as
+		we only know the physical length not the virtual
+	*/
+	if (!psLinuxMemArea->hBMHandle)
+	{
+		PVR_ASSERT(uiLength <= psLinuxMemArea->uiByteSize);
+	}
+
+	if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+	{
+		uiAreaOffset = psLinuxMemArea->uData.sSubAlloc.uiByteOffset;
+		psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+	}
+
+	/* Recursion surely isn't possible? */
+	PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+	switch(psLinuxMemArea->eAreaType)
+	{
+		case LINUX_MEM_AREA_VMALLOC:
+		{
+			if(is_vmalloc_addr(pvVirtRangeStart))
+			{
+				pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + uiAreaOffset;
+
+				/* Outside permissible range */
+				if(pvVirtRangeStart < pvMinVAddr)
+					goto err_blocked;
+			}
+			else
+			{
+				/* If this isn't a vmalloc address, assume we're flushing by
+				 * user-virtual. Compute the mmap base vaddr and use this to
+				 * compute the offset in vmalloc space.
+				 */
+
+				pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+				                               pvVirtRangeStart, uiLength);
+				if(!pvMinVAddr)
+					goto err_blocked;
+
+#if defined(USE_PHYSICAL_CACHE_OP)
+				/*
+				 * We don't need to worry about cache aliasing here because
+				 * we have already flushed the virtually-indexed caches (L1
+				 * etc.) by the supplied user-virtual addresses.
+				 *
+				 * The vmalloc address will only be used to determine
+				 * affected physical pages for outer cache flushing.
+				 */
+				pvPhysRangeStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
+						(uiAreaOffset & PAGE_MASK) + (pvVirtRangeStart - pvMinVAddr);
+#endif
+			}
+			break;
+		}
+
+		case LINUX_MEM_AREA_EXTERNAL_KV:
+		{
+			/* We'll only see bPhysContig for frame buffers, and we shouldn't
+			 * be flushing those (they're write combined or uncached).
+			 */
+			if (psLinuxMemArea->uData.sExternalKV.bPhysContig == IMG_TRUE)
+			{
+				PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush contiguous external memory", __func__));
+				goto err_blocked;
+			}
+
+			/* If it has a kernel virtual address, something odd has happened.
+			 * We expect EXTERNAL_KV _only_ from the wrapping of ALLOC_PAGES.
+			 */
+			if (psLinuxMemArea->uData.sExternalKV.pvExternalKV != IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush external memory with a kernel virtual address", __func__));
+				goto err_blocked;
+			}
+
+			pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+			                               pvVirtRangeStart, uiLength);
+			if(!pvMinVAddr)
+				goto err_blocked;
+
+			break;
+		}
+
+		case LINUX_MEM_AREA_ALLOC_PAGES:
+		{
+			pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+			                               pvVirtRangeStart, uiLength);
+			if(!pvMinVAddr)
+				goto err_blocked;
+
+			break;
+		}
+
+		default:
+			PVR_DBG_BREAK;
+			goto err_blocked;
+	}
+
+#if defined(USE_PHYSICAL_CACHE_OP)
+	switch(psLinuxMemArea->eAreaType)
+	{
+		case LINUX_MEM_AREA_VMALLOC:
+		{
+			pfnMemAreaToPhys = VMallocAreaToPhys;
+			break;
+		}
+
+		case LINUX_MEM_AREA_EXTERNAL_KV:
+		{
+			uPageNumOffset = ((uiAreaOffset & PAGE_MASK) + (pvPhysRangeStart - pvMinVAddr)) >> PAGE_SHIFT;
+			pfnMemAreaToPhys = ExternalKVAreaToPhys;
+			break;
+		}
+
+		case LINUX_MEM_AREA_ALLOC_PAGES:
+		{
+			uPageNumOffset = ((uiAreaOffset & PAGE_MASK) + (pvPhysRangeStart - pvMinVAddr)) >> PAGE_SHIFT;
+
+			if (psLinuxMemArea->hBMHandle)
+				pfnMemAreaToPhys = AllocPagesSparseAreaToPhys;
+			else
+				pfnMemAreaToPhys = AllocPagesAreaToPhys;
+
+			break;
+		}
+
+		default:
+			PVR_DBG_BREAK;
+	}
+#endif
+
+#if defined(USE_VIRTUAL_CACHE_OP)
+	DoVirtualCacheOp(hOSMemHandle,
+	                 ui32ByteOffset,
+	                 pvVirtRangeStart,
+	                 uiLength,
+	                 pfnVirtualCacheOp);
+#endif
+
+	LinuxUnLockMutex(&g_sMMapMutex);
+
+#if defined(USE_PHYSICAL_CACHE_OP)
+	PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
+
+	DoPhysicalCacheOp(psLinuxMemArea,
+	                  pvPhysRangeStart,
+	                  uiLength,
+	                  uPageNumOffset,
+	                  pfnMemAreaToPhys,
+	                  pfnPhysicalCacheOp);
+#endif
+
+	return IMG_TRUE;
+
+err_blocked:
+	PVR_DPF((PVR_DBG_WARNING, "%s: Blocked cache op on virtual range "
+							  "%p-%p (type %d)", __func__,
+			 pvVirtRangeStart, pvVirtRangeStart + uiLength,
+			 psLinuxMemArea->eAreaType));
+	LinuxUnLockMutex(&g_sMMapMutex);
+	return IMG_FALSE;
+}
+
+#if defined(__i386__) || defined (__x86_64__)
+
+#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
+
+static void per_cpu_cache_flush(void *arg)
+{
+    PVR_UNREFERENCED_PARAMETER(arg);
+    wbinvd();
+}
+
+static void x86_flush_cache_range(const void *pvStart, const void *pvEnd)
+{
+	IMG_BYTE *pbStart = (IMG_BYTE *)pvStart;
+	IMG_BYTE *pbEnd = (IMG_BYTE *)pvEnd;
+	IMG_BYTE *pbBase;
+
+	pbEnd = (IMG_BYTE *)ROUND_UP((IMG_UINTPTR_T)pbEnd,
+								 boot_cpu_data.x86_clflush_size);
+
+	mb();
+	for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size)
+	{
+		clflush(pbBase);
+	}
+	mb();
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+	/* No clean feature on x86 */
+	ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+	ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length)
+{
+	/* Write-back and invalidate */
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
+							   x86_flush_cache_range);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length)
+{
+	/* No clean feature on x86 */
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
+							   x86_flush_cache_range);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+									 IMG_UINT32 ui32ByteOffset,
+									 IMG_VOID *pvRangeAddrStart,
+									 IMG_UINT32 ui32Length)
+{
+	/* No invalidate-only support */
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
+							   x86_flush_cache_range);
+}
+
+#elif defined(__arm__) || defined(__aarch64__)
+
+static void per_cpu_cache_flush(void *arg)
+{
+	PVR_UNREFERENCED_PARAMETER(arg);
+#if defined(__aarch64__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0))
+	/*
+		NOTE: Regarding arm64 global flush support on >= Linux v4.2:
+		- Global cache flush support is deprecated from v4.2 onwards
+		- Cache maintenance is done using UM/KM VA maintenance _only_
+		- If you find that more time is spent in VA cache maintenance
+			- Implement arm64 assembly sequence for global flush here
+				- asm volatile ();
+		- If you do not want to implement the global cache assembly
+			- Disable KM cache maintenance support in UM cache.c
+			- Remove this PVR_LOG message
+	*/
+	PVR_LOG(("arm64: Global d-cache flush assembly not implemented"));
+#else
+	flush_cache_all();
+#endif
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+	/* No full (inner) cache clean op */
+	ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE)
+	outer_clean_range(0, ULONG_MAX);
+#endif
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+	ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && \
+	(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+	/* To use the "deferred flush" (not clean) DDK feature you need a kernel
+	 * implementation of outer_flush_all() for ARM CPUs with an outer cache
+	 * controller (e.g. PL310, common with Cortex A9 and later).
+	 *
+	 * Reference DDKs don't require this functionality, as they will only
+	 * clean the cache, never flush (clean+invalidate) it.
+	 */
+	outer_flush_all();
+#endif
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
+static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
+{
+	return (size_t)((char *)pvEnd - (char *)pvStart);
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+
+static void pvr_dmac_inv_range(const void *pvStart, const void *pvEnd)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+	dmac_inv_range(pvStart, pvEnd);
+#else
+	dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_FROM_DEVICE);
+#endif
+}
+
+static void pvr_dmac_clean_range(const void *pvStart, const void *pvEnd)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
+	dmac_clean_range(pvStart, pvEnd);
+#else
+	dmac_map_area(pvStart, pvr_dmac_range_len(pvStart, pvEnd), DMA_TO_DEVICE);
+#endif
+}
+
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
+
+static void pvr_flush_range(phys_addr_t pStart, phys_addr_t pEnd)
+{
+#if defined(__aarch64__)
+	struct dma_map_ops *dma_ops = get_dma_ops(PVRLDMGetDevice());
+	dma_ops->sync_single_for_device(NULL, pStart, pEnd - pStart, DMA_TO_DEVICE);
+	dma_ops->sync_single_for_cpu(NULL, pStart, pEnd - pStart, DMA_FROM_DEVICE);
+#else
+	arm_dma_ops.sync_single_for_device(NULL, pStart, pEnd - pStart, DMA_TO_DEVICE);
+	arm_dma_ops.sync_single_for_cpu(NULL, pStart, pEnd - pStart, DMA_FROM_DEVICE);
+#endif
+}
+
+static void pvr_clean_range(phys_addr_t pStart, phys_addr_t pEnd)
+{
+#if defined(__aarch64__)
+	struct dma_map_ops *dma_ops = get_dma_ops(PVRLDMGetDevice());
+	dma_ops->sync_single_for_device(NULL, pStart, pEnd - pStart, DMA_TO_DEVICE);
+#else
+	arm_dma_ops.sync_single_for_device(NULL, pStart, pEnd - pStart, DMA_TO_DEVICE);
+#endif
+
+}
+
+static void pvr_invalidate_range(phys_addr_t pStart, phys_addr_t pEnd)
+{
+#if defined(__aarch64__)
+	struct dma_map_ops *dma_ops = get_dma_ops(PVRLDMGetDevice());
+	dma_ops->sync_single_for_cpu(NULL, pStart, pEnd - pStart, DMA_FROM_DEVICE);
+#else
+	arm_dma_ops.sync_single_for_cpu(NULL, pStart, pEnd - pStart, DMA_FROM_DEVICE);
+#endif
+}
+
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length)
+{
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+	                           pvRangeAddrStart, ui32Length,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+	                           pvr_flush_range
+#elif defined(CONFIG_OUTER_CACHE)
+	                           dmac_flush_range, outer_flush_range
+#else
+	                           dmac_flush_range
+#endif
+	                           );
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length)
+{
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+	                           pvRangeAddrStart, ui32Length,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+	                           pvr_clean_range
+#elif defined(CONFIG_OUTER_CACHE)
+	                           pvr_dmac_clean_range, outer_clean_range
+#else
+	                           pvr_dmac_clean_range
+#endif
+	                           );
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+									 IMG_UINT32 ui32ByteOffset,
+									 IMG_VOID *pvRangeAddrStart,
+									 IMG_UINT32 ui32Length)
+{
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+	                           pvRangeAddrStart, ui32Length,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+	                           pvr_invalidate_range
+#elif defined(CONFIG_OUTER_CACHE)
+	                           pvr_dmac_inv_range, outer_inv_range
+#else
+	                           pvr_dmac_inv_range
+#endif
+	                           );
+}
+
+#elif defined(__mips__)
+
+/* 
+ * dmac cache functions are supposed to be used for dma 
+ * memory which comes from dma-able memory. However examining
+ * the implementation of dmac cache functions and experimenting,
+ * can assert that dmac functions are safe to use for high-mem
+ * memory as well for our OS{Clean/Flush/Invalidate}Cache functions
+ * 
+ */
+
+static inline size_t pvr_dma_range_len(const void *pvStart, const void *pvEnd)
+{
+	return (size_t)((char *)pvEnd - (char *)pvStart);
+}
+
+static void pvr_dma_cache_wback_inv(const void *pvStart, const void *pvEnd)
+{
+	size_t uLength = pvr_dma_range_len(pvStart, pvEnd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+	dma_cache_sync(NULL, (void *)pvStart, uLength, DMA_BIDIRECTIONAL);
+#else
+	dma_cache_wback_inv((unsigned long)pvStart, uLength);
+#endif
+}
+
+static void pvr_dma_cache_wback(const void *pvStart, const void *pvEnd)
+{
+	size_t uLength = pvr_dma_range_len(pvStart, pvEnd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+	dma_cache_sync(NULL, (void *)pvStart, uLength, DMA_TO_DEVICE);
+#else
+	dma_cache_wback((unsigned long)pvStart, uLength);
+#endif
+}
+
+static void pvr_dma_cache_inv(const void *pvStart, const void *pvEnd)
+{
+	size_t uLength = pvr_dma_range_len(pvStart, pvEnd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
+	dma_cache_sync(NULL, (void *)pvStart, uLength, DMA_FROM_DEVICE);
+#else
+	dma_cache_inv((unsigned long)pvStart, uLength);
+#endif
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+	/* dmac functions flush full cache if size is larger than
+	 * {s,d}-cache size. This is a workaround for the fact that
+	 * __flush_cache_all is not an exported symbol. Please
+	 * replace with custom function if available in latest
+	 * version of linux being used.
+	 * Arbitrary large number (1MB) which should be larger than 
+	 * mips {s,d}-cache sizes for some time in future.
+	 * */
+	pvr_dma_cache_wback(0, (const void *)0x200000);
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+	/* dmac functions flush full cache if size is larger than
+	 * {s,d}-cache size. This is a workaround for the fact that
+	 * __flush_cache_all is not an exported symbol. Please
+	 * replace with custom function if available in latest
+	 * version of linux being used.
+	 * Arbitrary large number (1MB) which should be larger than 
+	 * mips {s,d}-cache sizes for some time in future.
+	 * */
+	pvr_dma_cache_wback_inv(0, (const void *)0x200000);
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length)
+{
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+							   pvRangeAddrStart, ui32Length,
+							   pvr_dma_cache_wback_inv);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length)
+{
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+							   pvRangeAddrStart, ui32Length,
+							   pvr_dma_cache_wback);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+									 IMG_UINT32 ui32ByteOffset,
+									 IMG_VOID *pvRangeAddrStart,
+									 IMG_UINT32 ui32Length)
+{
+	return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+							   pvRangeAddrStart, ui32Length,
+							   pvr_dma_cache_inv);
+}
+
+#else
+
+#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"
+
+#endif
+
+typedef struct _AtomicStruct
+{
+	atomic_t RefCount;
+} AtomicStruct;
+
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount)
+{
+	AtomicStruct *psRefCount;
+
+	psRefCount = kmalloc(sizeof(AtomicStruct), GFP_KERNEL);
+	if (psRefCount == NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+	atomic_set(&psRefCount->RefCount, 0);
+	
+	*ppvRefCount = psRefCount;
+	return PVRSRV_OK;
+}
+
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount)
+{
+	AtomicStruct *psRefCount = pvRefCount;
+
+	PVR_ASSERT(atomic_read(&psRefCount->RefCount) == 0);
+	kfree(psRefCount);
+}
+
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount)
+{
+	AtomicStruct *psRefCount = pvRefCount;
+
+	atomic_inc(&psRefCount->RefCount);
+}
+
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount)
+{
+	AtomicStruct *psRefCount = pvRefCount;
+
+	return atomic_dec_and_test(&psRefCount->RefCount) ? IMG_TRUE:IMG_FALSE;
+}
+
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount)
+{
+	AtomicStruct *psRefCount = pvRefCount;
+
+	return (IMG_UINT32) atomic_read(&psRefCount->RefCount);
+}
+
+IMG_VOID OSReleaseBridgeLock(IMG_VOID)
+{
+       LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+IMG_VOID OSReacquireBridgeLock(IMG_VOID)
+{
+       LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+}
+
+typedef struct _OSTime
+{
+	unsigned long ulTime;
+} OSTime;
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32USOffset)
+{
+	OSTime *psOSTime;
+
+	psOSTime = kmalloc(sizeof(OSTime), GFP_KERNEL);
+	if (psOSTime == IMG_NULL)
+	{
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+
+	psOSTime->ulTime = jiffies + usecs_to_jiffies(ui32USOffset);
+	*pvRet = psOSTime;
+	return PVRSRV_OK;
+}
+
+
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData)
+{
+	OSTime *psOSTime = pvData;
+
+	if (time_is_before_jiffies(psOSTime->ulTime))
+	{
+		return IMG_TRUE;
+	}
+	return IMG_FALSE;
+}
+
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData)
+{
+	kfree(pvData);
+}
+
+IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size)
+{
+	strncpy(pszName, current->comm, MIN(ui32Size,TASK_COMM_LEN));
+}
+
+/* One time osfunc initialisation */
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    {
+        psTimerWorkQueue = create_workqueue("pvr_timer");
+        if (psTimerWorkQueue == NULL)
+        {
+	    PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));		
+	    return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+
+        }
+    }
+#endif
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+    {
+	IMG_UINT32 ui32i;
+
+        for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+        {
+            TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+	    INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+        }
+    }
+#endif
+
+#if defined(SUPPORT_ION) && !defined(LMA)
+	{
+		PVRSRV_ERROR eError;
+		eError = IonInit();
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: IonInit failed", __FUNCTION__));
+		}
+	}
+#endif
+    return PVRSRV_OK;
+}
+
+/*
+ * Osfunc deinitialisation.
+ * Note that PVROSFuncInit may not have been called
+ */
+IMG_VOID PVROSFuncDeInit(IMG_VOID)
+{
+#if defined (SUPPORT_ION)
+	IonDeinit();
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+    if (psTimerWorkQueue != NULL)
+    {
+	destroy_workqueue(psTimerWorkQueue);
+    }
+#endif
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c b/drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c
new file mode 100644
index 0000000..9b014dc
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/osperproc.c
@@ -0,0 +1,155 @@
+/*************************************************************************/ /*!
+@Title          Linux specific per process data functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+
+#if defined (SUPPORT_ION)
+#include <linux/err.h>
+#include "ion.h"
+extern struct ion_device *gpsIonDev;
+#endif
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+	PVRSRV_ERROR eError;
+	IMG_HANDLE hBlockAlloc;
+	PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+	eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+				phOsPrivateData,
+				&hBlockAlloc,
+				"Environment per Process Data");
+
+	if (eError != PVRSRV_OK)
+	{
+		*phOsPrivateData = IMG_NULL;
+
+		PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+		return eError;
+	}
+
+	psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+	OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+	psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+	/* Linux specific mmap processing */
+	LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	/* Linked list of PVRSRV_FILE_PRIVATE_DATA structures */
+	INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+#if defined(SUPPORT_ION)
+	OSSNPrintf(psEnvPerProc->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%d", OSGetCurrentProcessIDKM());
+	psEnvPerProc->psIONClient =
+		ion_client_create(gpsIonDev,
+						  psEnvPerProc->azIonClientName);
+ 
+	if (IS_ERR_OR_NULL(psEnvPerProc->psIONClient))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "OSPerProcessPrivateDataInit: Couldn't create "
+								"ion client for per process data"));
+		return PVRSRV_ERROR_OUT_OF_MEMORY;
+	}
+#endif /* defined(SUPPORT_ION) */
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+	PVRSRV_ERROR eError;
+	PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+	if (hOsPrivateData == IMG_NULL)
+	{
+		return PVRSRV_OK;
+	}
+
+	psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+#if defined(SUPPORT_ION)
+	if (psEnvPerProc->psIONClient)
+	{
+		ion_client_destroy(psEnvPerProc->psIONClient);
+		psEnvPerProc->psIONClient = IMG_NULL;
+	}
+#endif /* defined(SUPPORT_ION) */
+
+	/* Linux specific mmap processing */
+	LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+	/* Remove per process /proc entries */
+	RemovePerProcessProcDir(psEnvPerProc);
+
+	eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+				sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+				hOsPrivateData,
+				psEnvPerProc->hBlockAlloc);
+	/*not nulling pointer, copy on stack*/
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+	}
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+	return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+	if(!gui32ReleasePID)
+		return NULL;
+	return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c
new file mode 100644
index 0000000..548e8dc
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pdump.c
@@ -0,0 +1,855 @@
+/*************************************************************************/ /*!
+@Title          Parameter dump macro target routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if defined (SUPPORT_SGX) || defined (SUPPORT_VGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#if defined (SUPPORT_SGX)
+#include "sgxdefs.h" /* Is this still needed? */
+#endif
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#if defined (SUPPORT_SGX)
+#include "sgxmmu.h"/* Is this still needed? */
+#endif
+#include "mm.h"
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+#include <linux/kernel.h> // sprintf
+#include <linux/string.h> // strncpy, strlen
+#include <linux/mutex.h>
+
+static IMG_BOOL PDumpWriteString2		(IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock			(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame				(PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_VOID DbgSetMarker			(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+
+#define PDUMP_DATAMASTER_PIXEL		(1)
+#define PDUMP_DATAMASTER_EDM		(3)
+
+/*
+	Maximum file size to split output files
+*/
+#define MAX_FILE_SIZE	0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+DEFINE_MUTEX(sPDumpLock);
+DEFINE_MUTEX(sPDumpMsgLock);
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = {	"ParamStream2",
+												"ScriptStream2",
+												"DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+	PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+	IMG_UINT32 ui32ParamFileNum;
+
+	IMG_CHAR *pszMsg;
+	IMG_CHAR *pszScript;
+	IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX			PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX		PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX	PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+	return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+/*!
+ * \name	PDumpOSGetScriptString
+ */
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+									IMG_UINT32 *pui32MaxLen)
+{
+	*phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+	*pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+	if ((!*phScript) || PDumpSuspended())
+	{
+		return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+	}
+	return PVRSRV_OK;
+}
+
+/*!
+ * \name	PDumpOSGetMessageString
+ */
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
+									 IMG_UINT32 *pui32MaxLen)
+{
+	*ppszMsg = gsDBGPdumpState.pszMsg;
+	*pui32MaxLen = SZ_MSG_SIZE_MAX;
+	if ((!*ppszMsg) || PDumpSuspended())
+	{
+		return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+	}
+	return PVRSRV_OK;
+}
+
+/*!
+ * \name	PDumpOSGetFilenameString
+ */
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+									 IMG_UINT32 *pui32MaxLen)
+{
+	*ppszFile = gsDBGPdumpState.pszFile;
+	*pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+	if ((!*ppszFile) || PDumpSuspended())
+	{
+		return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+	}
+	return PVRSRV_OK;
+}
+
+/*!
+ * \name	PDumpOSWriteString2
+ */
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+	return PDumpWriteString2(hScript, ui32Flags);
+}
+
+/*!
+ * \name	PDumpOSBufprintf
+ */
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+	IMG_CHAR* pszBuf = hBuf;
+	IMG_INT32 n;
+	va_list	vaArgs;
+
+	va_start(vaArgs, pszFormat);
+
+	n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+	va_end(vaArgs);
+
+	if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)	/* glibc >= 2.1 or glibc 2.0 */
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+		return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+	}
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+	g_ui32EveryLineCounter++;
+#endif
+	return PVRSRV_OK;
+}
+
+/*!
+ * \name	PDumpOSVSprintf
+ */
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+	IMG_INT32 n;
+
+	n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+	if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)	/* glibc >= 2.1 or glibc 2.0 */
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+		return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+ * \name	PDumpOSDebugPrintf
+ */
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+	PVR_UNREFERENCED_PARAMETER(pszFormat);
+
+	/* FIXME: Implement using services PVR_DBG or otherwise with kprintf */
+}
+
+/*!
+ * \name	PDumpOSSprintf
+ */
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+	IMG_INT32 n;
+	va_list	vaArgs;
+
+	va_start(vaArgs, pszFormat);
+
+	n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+	va_end(vaArgs);
+
+	if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)	/* glibc >= 2.1 or glibc 2.0 */
+	{
+		PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+		return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+	}
+
+	return PVRSRV_OK;
+}
+
+/*!
+ * \name	PDumpOSBuflen
+ */
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+	IMG_CHAR* pszBuf = hBuffer;
+	IMG_UINT32 ui32Count = 0;
+
+	while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+	{
+		ui32Count++;
+	}
+	return(ui32Count);
+}
+
+/*!
+ * \name	PDumpOSVerifyLineEnding
+ */
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+	IMG_UINT32 ui32Count;
+	IMG_CHAR* pszBuf = hBuffer;
+
+	/* strlen */
+	ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+	/* Put \r \n sequence at the end if it isn't already there */
+	if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+	{
+		pszBuf[ui32Count] = '\n';
+		ui32Count++;
+		pszBuf[ui32Count] = '\0';
+	}
+	if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+	{
+		pszBuf[ui32Count-1] = '\r';
+		pszBuf[ui32Count] = '\n';
+		ui32Count++;
+		pszBuf[ui32Count] = '\0';
+	}
+}
+
+/*!
+ * \name	PDumpOSGetStream
+ */
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+	return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+/*!
+ * \name	PDumpOSGetStreamOffset
+ */
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+	PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+	return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+/*!
+ * \name	PDumpOSGetParamFileNum
+ */
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+	return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+/*!
+ * \name	PDumpOSWriteString
+ */
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+		IMG_UINT8 *psui8Data,
+		IMG_UINT32 ui32Size,
+		IMG_UINT32 ui32Flags)
+{
+	PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+	return PDumpWriteILock(psStream,
+					psui8Data,
+					ui32Size,
+					ui32Flags);
+}
+
+/*!
+ * \name	PDumpOSCheckForSplitting
+ */
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+	/* File size limit not implemented for this OS.
+	 */
+	PVR_UNREFERENCED_PARAMETER(hStream);
+	PVR_UNREFERENCED_PARAMETER(ui32Size);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+}
+
+/*!
+ * \name	PDumpOSJTInitialised
+ */
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+	if(gpfnDbgDrv)
+	{
+		return IMG_TRUE;
+	}
+	return IMG_FALSE;
+}
+
+/*!
+ * \name	PDumpOSIsSuspended
+ */
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+	return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+/*!
+ * \name	PDumpOSCPUVAddrToDevPAddr
+ */
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+        IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_UINT8 *pui8LinAddr,
+		IMG_UINT32 ui32PageSize,
+		IMG_DEV_PHYADDR *psDevPAddr)
+{
+	IMG_CPU_PHYADDR	sCpuPAddr;
+
+	PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32PageSize);   /* for when no assert */
+
+	/* Caller must now alway supply hOSMemHandle, even though we only (presently)
+	   use it here in the linux implementation */
+	   
+	PVR_ASSERT (hOSMemHandle != IMG_NULL);
+	
+	sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+	PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+	/* convert CPU physical addr to device physical */
+	*psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+}
+
+/*!
+ * \name	PDumpOSCPUVAddrToPhysPages
+ */
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_PUINT8 pui8LinAddr,
+		IMG_UINTPTR_T ui32DataPageMask,
+		IMG_UINT32 *pui32PageOffset)
+{
+	if(hOSMemHandle)
+	{
+		/*
+		 * If a Services memory handle is provided then use it.
+		 */
+		IMG_CPU_PHYADDR     sCpuPAddr;
+
+		PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+		sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+	    *pui32PageOffset = sCpuPAddr.uiAddr & ui32DataPageMask;
+	}
+	else
+	{
+		PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+		PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+		*pui32PageOffset = ((IMG_UINTPTR_T)pui8LinAddr & ui32DataPageMask);
+	}
+}
+
+/*!
+ *	\name	PDumpOSDebugDriverWrite
+ */
+IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
+									PDUMP_DDWMODE eDbgDrvWriteMode,
+									IMG_UINT8 *pui8Data,
+									IMG_UINT32 ui32BCount,
+									IMG_UINT32 ui32Level,
+									IMG_UINT32 ui32DbgDrvFlags)
+{
+	switch(eDbgDrvWriteMode)
+	{
+		case PDUMP_WRITE_MODE_CONTINUOUS:
+			PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+			return gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, ui32Level);
+		case PDUMP_WRITE_MODE_LASTFRAME:
+			return gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, ui32Level, ui32DbgDrvFlags);
+		case PDUMP_WRITE_MODE_BINCM:
+			PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+			return gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, ui32Level);
+		case PDUMP_WRITE_MODE_PERSISTENT:
+			PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+			return gpfnDbgDrv->pfnWritePersist(psStream, pui8Data, ui32BCount, ui32Level);
+		default:
+			PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+			break;
+	}
+	return 0xFFFFFFFFU;
+}
+
+/*!
+ *	\name	PDumpOSReleaseExecution
+ */
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID)
+{
+	OSReleaseThreadQuanta();
+}
+
+/**************************************************************************
+ * Function Name  : PDumpInit
+ * Outputs        : None
+ * Returns        :
+ * Description    : Reset connection to vldbgdrv
+ *					Then try to connect to PDUMP streams
+**************************************************************************/
+IMG_VOID PDumpInit(IMG_VOID)
+{
+	IMG_UINT32 i;
+	DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+	/* If we tried this earlier, then we might have connected to the driver
+	 * But if pdump.exe was running then the stream connected would fail
+	 */
+	if (!gpfnDbgDrv)
+	{
+		DBGDrvGetServiceTable(&gpfnDbgDrv);
+
+
+		// If something failed then no point in trying to connect streams
+		if (gpfnDbgDrv == IMG_NULL)
+		{
+			return;
+		}
+		
+		/*
+		 * Pass the connection notify callback
+		 */
+		sConnectNotifier.pfnConnectNotifier = &PDumpConnectionNotify;
+		gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+		if(!gsDBGPdumpState.pszFile)
+		{
+			if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+				"Filename string") != PVRSRV_OK)
+			{
+				goto init_failed;
+			}
+		}
+
+		if(!gsDBGPdumpState.pszMsg)
+		{
+			if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+				"Message string") != PVRSRV_OK)
+			{
+				goto init_failed;
+			}
+		}
+
+		if(!gsDBGPdumpState.pszScript)
+		{
+			if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+				"Script string") != PVRSRV_OK)
+			{
+				goto init_failed;
+			}
+		}
+
+		for(i=0; i < PDUMP_NUM_STREAMS; i++)
+		{
+			gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+														DEBUG_CAPMODE_FRAMED,
+														DEBUG_OUTMODE_STREAMENABLE,
+														0,
+														10);
+
+			gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+			gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+		}
+
+		PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+		PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FAMILY);
+		PDUMPCOMMENT("Start of Init Phase");
+	}
+
+	return;
+
+init_failed:
+
+	if(gsDBGPdumpState.pszFile)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+		gsDBGPdumpState.pszFile = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszScript)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+		gsDBGPdumpState.pszScript = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszMsg)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+		gsDBGPdumpState.pszMsg = IMG_NULL;
+	}
+
+	/*
+	 * Remove the connection notify callback
+	 */
+	sConnectNotifier.pfnConnectNotifier = 0;
+	gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+	gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+	IMG_UINT32 i;
+	DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+	for(i=0; i < PDUMP_NUM_STREAMS; i++)
+	{
+		gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+	}
+
+	if(gsDBGPdumpState.pszFile)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+		gsDBGPdumpState.pszFile = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszScript)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+		gsDBGPdumpState.pszScript = IMG_NULL;
+	}
+
+	if(gsDBGPdumpState.pszMsg)
+	{
+		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+		gsDBGPdumpState.pszMsg = IMG_NULL;
+	}
+
+	/*
+	 * Remove the connection notify callback
+	 */
+	sConnectNotifier.pfnConnectNotifier = 0;
+	gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+	gpfnDbgDrv = IMG_NULL;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpStartInitPhaseKM
+ * Inputs         : None
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Resume init phase state
+**************************************************************************/
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+	if (gpfnDbgDrv)
+	{
+		PDUMPCOMMENT("Start Init Phase");
+		for(i=0; i < PDUMP_NUM_STREAMS; i++)
+		{
+			gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+		}
+	}
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpStopInitPhaseKM
+ * Inputs         : None
+ * Outputs        : None
+ * Returns        : None
+ * Description    : End init phase state
+**************************************************************************/
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+	IMG_UINT32 i;
+
+	if (gpfnDbgDrv)
+	{
+		PDUMPCOMMENT("Stop Init Phase");
+
+		for(i=0; i < PDUMP_NUM_STREAMS; i++)
+		{
+			gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+		}
+	}
+	return PVRSRV_OK;
+}
+
+/**************************************************************************
+ * Function Name  : PDumpIsLastCaptureFrameKM
+ * Inputs         : None
+ * Outputs        : None
+ * Returns        : True or false
+ * Description    : Tests whether the current frame is being pdumped
+**************************************************************************/
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+	return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+/**************************************************************************
+ * Function Name  : PDumpIsCaptureFrameKM
+ * Inputs         : None
+ * Outputs        : None
+ * Returns        : True or false
+ * Description    : Tests whether the current frame is being pdumped
+**************************************************************************/
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID)
+{
+	if (PDumpSuspended())
+	{
+		return IMG_FALSE;
+	}
+	return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+/**************************************************************************
+ * Function Name  : PDumpSetFrameKM
+ * Inputs         : None
+ * Outputs        : None
+ * Returns        : None
+ * Description    : Sets a frame
+**************************************************************************/
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame)
+{
+	IMG_UINT32	ui32Stream;
+
+	for	(ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+	{
+		if	(gsDBGPdumpState.psStream[ui32Stream])
+		{
+			DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+
+/*****************************************************************************
+ FUNCTION	:	PDumpWriteString2
+
+ PURPOSE	:
+
+ PARAMETERS	:
+
+ RETURNS	:
+*****************************************************************************/
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+	return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+/*****************************************************************************
+ FUNCTION	: PDumpWriteILock
+
+ PURPOSE	: Writes, making sure it all goes...
+
+ PARAMETERS	:
+
+ RETURNS	:
+*****************************************************************************/
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+	IMG_UINT32 ui32Written = 0;
+	if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteILock: Failed to write 0x%x bytes to stream 0x%p", ui32Count, psStream));
+		return IMG_TRUE;
+	}
+
+
+	/*
+		Set the stream marker to split output files
+	*/
+
+	if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+	{
+		IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+		if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+		{
+			if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+			{
+				DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+				gsDBGPdumpState.ui32ParamFileNum++;
+			}
+		}
+	}
+
+	ui32Written = DbgWrite(psStream, pui8Data, ui32Count, ui32Flags);
+
+	if (ui32Written == 0xFFFFFFFF)
+	{
+		return IMG_FALSE;
+	}
+
+	return IMG_TRUE;
+}
+
+/*****************************************************************************
+ FUNCTION	:	DbgSetFrame
+
+ PURPOSE	:	Sets the frame in the stream
+
+ PARAMETERS	:	psStream	- Stream pointer
+				ui32Frame		- Frame number to set
+
+ RETURNS	: 	None
+*****************************************************************************/
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+	gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+/*****************************************************************************
+ FUNCTION	:	DbgSetMarker
+
+ PURPOSE	:	Sets the marker of the stream to split output files
+
+ PARAMETERS	:	psStream	- Stream pointer
+				ui32Marker	- Marker number to set
+
+ RETURNS	: 	None
+*****************************************************************************/
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+	gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+	atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+	atomic_dec(&gsPDumpSuspended);
+}
+
+/* Set to 1 if you want to debug PDump locking issues */
+#define DEBUG_PDUMP_LOCKS 0
+
+#if DEBUG_PDUMP_LOCKS
+static IMG_UINT32 ui32Count=0;
+static IMG_UINT32 aui32LockLine[2] = {0};
+static IMG_UINT32 aui32UnlockLine[2] = {0};
+static IMG_UINT32 ui32LockLineCount = 0;
+static IMG_UINT32 ui32UnlockLineCount = 0;
+#endif
+
+IMG_VOID PDumpOSLock(IMG_UINT32 ui32Line)
+{
+#if DEBUG_PDUMP_LOCKS
+	aui32LockLine[ui32LockLineCount++ % 2] = ui32Line;
+	ui32Count++;
+	if (ui32Count == 2)
+	{
+		IMG_UINT32 i;
+		printk(KERN_ERR "Double lock\n");
+		dump_stack();
+		for (i=0;i<2;i++)
+		{
+			printk(KERN_ERR "Lock[%d] = %d, Unlock[%d] = %d\n", i, aui32LockLine[i],i, aui32UnlockLine[i]);
+		}
+	}
+#endif
+	mutex_lock(&sPDumpLock);
+}
+
+IMG_VOID PDumpOSUnlock(IMG_UINT32 ui32Line)
+{
+	mutex_unlock(&sPDumpLock);
+#if DEBUG_PDUMP_LOCKS
+	aui32UnlockLine[ui32UnlockLineCount++ % 2] = ui32Line;
+	ui32Count--;
+#endif
+}
+
+IMG_VOID PDumpOSLockMessageBuffer(IMG_VOID)
+{
+	mutex_lock(&sPDumpMsgLock);
+}
+
+IMG_VOID PDumpOSUnlockMessageBuffer(IMG_VOID)
+{
+	mutex_unlock(&sPDumpMsgLock);
+}
+
+#endif /* #if defined (PDUMP) */
+#endif /* #if defined (SUPPORT_SGX) */
+/*****************************************************************************
+ End of file (PDUMP.C)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h b/drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h
new file mode 100644
index 0000000..e2a6c74
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/private_data.h
@@ -0,0 +1,91 @@
+/*************************************************************************/ /*!
+@Title          Linux private data structure
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+/* This structure is required in the rare case that a process creates
+ * a connection to services, but before closing the file descriptor,
+ * does a fork(). This fork() will duplicate the file descriptor in the
+ * child process. If the parent process dies before the child, this can
+ * cause the PVRSRVRelease() method to be called in a different process
+ * context than the original PVRSRVOpen(). This is bad because we need
+ * to update the per-process data reference count and/or free the
+ * per-process data. So we must keep a record of which PID's per-process
+ * data to inspect during ->release().
+ */
+
+typedef struct
+{
+	/* PID that created this services connection */
+	IMG_UINT32 ui32OpenPID;
+
+	/* Global kernel MemInfo handle */
+	IMG_HANDLE hKernelMemInfo;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	/* The private data is on a list in the per-process data structure */
+	struct list_head sDRMAuthListItem;
+
+	struct drm_file *psDRMFile;
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+	/* Globally unique "stamp" for kernel MemInfo */
+	IMG_UINT64 ui64Stamp;
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
+
+	/* Accounting for OSAllocMem */
+	IMG_HANDLE hBlockAlloc;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+	IMG_PVOID pPriv;	/*private data for extending this struct*/
+#endif
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif /* __INCLUDED_PRIVATE_DATA_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/proc.c b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.c
new file mode 100644
index 0000000..0f954c1
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.c
@@ -0,0 +1,1059 @@
+/*************************************************************************/ /*!
+@Title          Proc files implementation.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Functions for creating and reading proc filesystem entries.
+                Proc filesystem support must be built into the kernel for
+                these functions to be any use.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+
+struct pvr_proc_dir_entry {
+	struct proc_dir_entry *pde;
+	
+	pvr_next_proc_seq_t *next;
+	pvr_show_proc_seq_t *show;	
+	pvr_off2element_proc_seq_t *off2element;
+	pvr_startstop_proc_seq_t *startstop;
+	
+	pvr_proc_write_t *write;
+
+	IMG_VOID *data;
+};
+
+// The proc entry for our /proc/pvr directory
+static struct proc_dir_entry * dir;
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+	.open		= pvr_proc_open,
+	.read		= seq_read,
+	.write		= pvr_proc_write,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+	.start =	pvr_proc_seq_start,
+	.next =		pvr_proc_seq_next,
+	.stop =		pvr_proc_seq_stop,
+	.show =		pvr_proc_seq_show,
+};
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+static struct pvr_proc_dir_entry* g_pProcQueue;
+#endif
+static struct pvr_proc_dir_entry* g_pProcVersion;
+static struct pvr_proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct pvr_proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct pvr_proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#define PDE_DATA(x)    PDE(x)->data;
+#endif
+
+#ifdef DEBUG
+
+/*!
+******************************************************************************
+
+ @Function : ProcSeq1ElementOff2Element
+
+ @Description
+
+ Heleper Offset -> Element function for /proc files with only one entry
+ without header.
+
+ @Input  sfile : seq_file object related to /proc/ file
+
+ @Input  off : the offset into the buffer (id of object)
+
+ @Return : Pointer to element to be shown.
+
+*****************************************************************************/
+static void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+	PVR_UNREFERENCED_PARAMETER(sfile);
+	// Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
+	if(!off)
+		return (void*)2;
+	return NULL;
+}
+
+#endif
+
+/*!
+******************************************************************************
+
+ @Function : ProcSeq1ElementHeaderOff2Element
+
+ @Description
+
+ Heleper Offset -> Element function for /proc files with only one entry
+ with header.
+
+ @Input  sfile : seq_file object related to /proc/ file
+
+ @Input  off : the offset into the buffer (id of object)
+
+ @Return : Pointer to element to be shown.
+
+*****************************************************************************/
+static void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+	PVR_UNREFERENCED_PARAMETER(sfile);
+
+	if(!off)
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+	// Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
+	if(off == 1)
+		return (void*)2;
+
+	return NULL;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_open
+
+ @Description
+ File opening function passed to proc_dir_entry->proc_fops for /proc entries
+ created by CreateProcReadEntrySeq.
+
+ @Input  inode : inode entry of opened /proc file
+
+ @Input  file : file entry of opened /proc file
+
+ @Return      : 0 if no errors
+
+*****************************************************************************/
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+	IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+	struct seq_file *seq = (struct seq_file*)file->private_data;
+	struct pvr_proc_dir_entry* ppde = PDE_DATA(inode);
+
+	/* Add pointer to handlers to seq_file structure */
+	seq->private = ppde;
+	return ret;
+}
+
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_write
+
+ @Description
+ File writing function passed to proc_dir_entry->proc_fops for /proc files.
+ It's exacly the same function that is used as default one (->fs/proc/generic.c),
+ it calls proc_dir_entry->write_proc for writing procedure.
+
+*****************************************************************************/
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+		size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct pvr_proc_dir_entry * ppde;
+
+	PVR_UNREFERENCED_PARAMETER(ppos);
+	ppde = PDE_DATA(inode);
+
+	if (!ppde->write)
+		return -EIO;
+
+	return ppde->write(file, buffer, count, ppde->data);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_start
+
+ @Description
+ Seq_file start function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ This function ises off2element handler.
+
+ @Input  proc_seq_file : sequence file entry
+
+ @Input  pos : offset within file (id of entry)
+
+ @Return      : Pointer to element from we start enumeration (0 ends it)
+
+*****************************************************************************/
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+	struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
+	if(ppde->startstop != NULL)
+		ppde->startstop(proc_seq_file, IMG_TRUE);
+	return ppde->off2element(proc_seq_file, *pos);
+}
+
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_stop
+
+ @Description
+ Seq_file stop function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+
+ @Input  proc_seq_file : sequence file entry
+
+ @Input  v : current element pointer
+
+*****************************************************************************/
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+	struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
+	PVR_UNREFERENCED_PARAMETER(v);
+
+	if(ppde->startstop != NULL)
+		ppde->startstop(proc_seq_file, IMG_FALSE);
+}
+
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_next
+
+ @Description
+ Seq_file next element function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ It uses supplied 'next' handler for fetching next element (or 0 if there is no one)
+
+ @Input  proc_seq_file : sequence file entry
+
+ @Input  pos : offset within file (id of entry)
+
+ @Input  v : current element pointer
+
+ @Return   : next element pointer (or 0 if end)
+
+*****************************************************************************/
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+	struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
+	(*pos)++;
+	if(ppde->next != NULL)
+		return ppde->next( proc_seq_file, v, *pos );
+	return ppde->off2element(proc_seq_file, *pos);
+}
+
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_show
+
+ @Description
+ Seq_file show element function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ It call proper 'show' handler to show (dump) current element using seq_* functions
+
+ @Input  proc_seq_file : sequence file entry
+
+ @Input  v : current element pointer
+
+ @Return   : 0 if everything is OK
+
+*****************************************************************************/
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+	struct pvr_proc_dir_entry *ppde = (struct pvr_proc_dir_entry*)proc_seq_file->private;
+	ppde->show( proc_seq_file,v );
+	return 0;
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntryInDirSeq
+
+ @Description
+
+ Create a file under the given directory.  These dynamic files can be used at
+ runtime to get or set information about the device. Whis version uses seq_file
+ interface
+
+ @Input  pdir : parent directory
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+						supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input  whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+
+*****************************************************************************/
+static struct pvr_proc_dir_entry* CreateProcEntryInDirSeq(struct proc_dir_entry *pdir,
+                                                          const IMG_CHAR * name,
+                                                          IMG_VOID* data,
+                                                          pvr_next_proc_seq_t next_handler,
+                                                          pvr_show_proc_seq_t show_handler,
+                                                          pvr_off2element_proc_seq_t off2element_handler,
+                                                          pvr_startstop_proc_seq_t startstop_handler,
+                                                          pvr_proc_write_t whandler)
+{
+
+	struct pvr_proc_dir_entry * ppde;
+	mode_t mode;
+
+	if (!dir)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+		return NULL;
+	}
+
+	mode = S_IFREG;
+
+	if (show_handler)
+	{
+		mode |= S_IRUGO;
+	}
+
+	if (whandler)
+	{
+		mode |= S_IWUSR;
+	}
+
+	ppde = kmalloc(sizeof(struct pvr_proc_dir_entry), GFP_KERNEL);
+	if (!ppde)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+		return NULL;
+	}
+	
+	ppde->next        = next_handler;
+	ppde->show        = show_handler;
+	ppde->off2element = off2element_handler;
+	ppde->startstop   = startstop_handler;
+	ppde->write       = whandler;
+	ppde->data        = data;
+
+	ppde->pde=proc_create_data(name, mode, pdir, &pvr_proc_operations, ppde);
+
+	if (!ppde->pde)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: proc_create_data failed", PVRProcDirRoot, name));
+		kfree(ppde);
+		return NULL;
+	}
+	return ppde;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function :  CreateProcReadEntrySeq
+
+ @Description
+
+ Create a file under /proc/pvr.  These dynamic files can be used at runtime
+ to get information about the device.  Creation WILL fail if proc support is
+ not compiled into the kernel.  That said, the Linux kernel is not even happy
+ to build without /proc support these days. This version uses seq_file structure
+ for handling content generation.
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+						supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
+struct pvr_proc_dir_entry* CreateProcReadEntrySeq (const IMG_CHAR * name,
+                                                   IMG_VOID* data,
+                                                   pvr_next_proc_seq_t next_handler,
+                                                   pvr_show_proc_seq_t show_handler,
+                                                   pvr_off2element_proc_seq_t off2element_handler,
+                                                   pvr_startstop_proc_seq_t startstop_handler)
+{
+	return CreateProcEntrySeq(name,
+	                          data,
+	                          next_handler,
+	                          show_handler,
+	                          off2element_handler,
+	                          startstop_handler,
+	                          NULL);
+}
+
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntrySeq
+
+ @Description
+
+ @Description
+
+ Create a file under /proc/pvr.  These dynamic files can be used at runtime
+ to get information about the device.  Creation WILL fail if proc support is
+ not compiled into the kernel.  That said, the Linux kernel is not even happy
+ to build without /proc support these days. This version uses seq_file structure
+ for handling content generation and is fuller than CreateProcReadEntrySeq (it
+ supports write access);
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+						supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input  whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
+struct pvr_proc_dir_entry* CreateProcEntrySeq (const IMG_CHAR * name,
+                                               IMG_VOID* data,
+                                               pvr_next_proc_seq_t next_handler,
+                                               pvr_show_proc_seq_t show_handler,
+                                               pvr_off2element_proc_seq_t off2element_handler,
+                                               pvr_startstop_proc_seq_t startstop_handler,
+                                               pvr_proc_write_t whandler)
+{
+	return CreateProcEntryInDirSeq(dir,
+	                               name,
+	                               data,
+	                               next_handler,
+	                               show_handler,
+	                               off2element_handler,
+	                               startstop_handler,
+	                               whandler);
+}
+
+
+
+/*!
+******************************************************************************
+
+ @Function : CreatePerProcessProcEntrySeq
+
+ @Description
+
+ Create a file under /proc/pvr/<current process ID>.  Apart from the
+ directory where the file is created, this works the same way as
+ CreateProcEntry. It's seq_file version.
+
+
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+						supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input  whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
+struct pvr_proc_dir_entry* CreatePerProcessProcEntrySeq (const IMG_CHAR * name,
+                                                         IMG_VOID* data,
+                                                         pvr_next_proc_seq_t next_handler,
+                                                         pvr_show_proc_seq_t show_handler,
+                                                         pvr_off2element_proc_seq_t off2element_handler,
+                                                         pvr_startstop_proc_seq_t startstop_handler,
+                                                         pvr_proc_write_t whandler)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+    IMG_UINT32 ui32PID;
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+        return NULL;
+    }
+
+    ui32PID = OSGetCurrentProcessIDKM();
+
+    psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+    if (!psPerProc)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+        return NULL;
+    }
+
+    if (!psPerProc->psProcDir)
+    {
+        IMG_CHAR dirname[16];
+        IMG_INT ret;
+
+        ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+        if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+            return NULL;
+        }
+        else
+        {
+            psPerProc->psProcDir = proc_mkdir(dirname, dir);
+            if (!psPerProc->psProcDir)
+            {
+                PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+                         PVRProcDirRoot, ui32PID));
+                return NULL;
+            }
+	}
+    }
+
+    return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+                                   show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntries
+
+ @Description
+
+ Create a directory /proc/pvr and the necessary entries within it.  These
+ dynamic files can be used at runtime to get information about the device.
+ Creation might fail if proc support is not compiled into the kernel or if
+ there is no memory
+
+ @Input none
+
+ @Return nothing
+
+*****************************************************************************/
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+    dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+    if (!dir)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+#endif
+	g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+	g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+	if(!g_pProcVersion || !g_pProcSysNodes
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+		|| !g_pProcQueue
+#endif
+		)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+
+#ifdef DEBUG
+
+	g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+											ProcSeqShowDebugLevel,
+											ProcSeq1ElementOff2Element, NULL,
+										    (IMG_VOID*)PVRDebugProcSetLevel);
+	if(!g_pProcDebugLevel)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+	g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+											ProcSeqShowPowerLevel,
+											ProcSeq1ElementOff2Element, NULL,
+										    PVRProcSetPowerLevel);
+	if(!g_pProcPowerLevel)
+    {
+        PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+        return -ENOMEM;
+    }
+#endif
+#endif
+
+    return 0;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntrySeq
+
+ @Description
+
+ Remove a single node (created using *Seq function) under /proc/pvr.
+
+ @Input proc_entry : structure returned by Create function.
+
+ @Return nothing
+
+*****************************************************************************/
+IMG_VOID RemoveProcEntrySeq(struct pvr_proc_dir_entry* ppde)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+	remove_proc_entry(ppde->pde->name, dir);
+#else
+	proc_remove(ppde->pde);
+#endif
+	kfree(ppde);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcEntrySeq
+
+ @Description
+
+ Remove a single node under the per process proc directory (created by *Seq function).
+
+ Remove a single node (created using *Seq function) under /proc/pvr.
+
+ @Input proc_entry : structure returned by Create function.
+
+ @Return nothing
+
+*****************************************************************************/
+IMG_VOID RemovePerProcessProcEntrySeq(struct pvr_proc_dir_entry* ppde)
+{
+    PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+    psPerProc = LinuxTerminatingProcessPrivateData();
+    if (!psPerProc)
+    {
+        psPerProc = PVRSRVFindPerProcessPrivateData();
+        if (!psPerProc)
+        {
+            PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't remove proc entry, no per process data"));
+            return;
+        }
+    }
+
+    if (psPerProc->psProcDir)
+    {
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing per-process proc entry"));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+        remove_proc_entry(ppde->pde->name, psPerProc->psProcDir);
+#else
+	proc_remove(ppde->pde);
+#endif
+	kfree(ppde);
+    }
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntry
+
+ @Description
+
+ Remove a single node under /proc/pvr.
+
+ @Input name : the name of the node to remove
+
+ @Return nothing
+
+*****************************************************************************/
+static IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+    if (dir)
+    {
+        remove_proc_entry(name, dir);
+        PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+    }
+}
+
+
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcDir
+
+ @Description
+
+ Remove the per process directorty under /proc/pvr.
+
+ @Input psPerProc : environment specific per process data
+
+ @Return nothing
+
+*****************************************************************************/
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+    if (psPerProc->psProcDir)
+    {
+        while (psPerProc->psProcDir->subdir)
+        {
+            PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+            RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+        }
+        RemoveProcEntry(psPerProc->psProcDir->name);
+    }
+}
+#else
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+	proc_remove(psPerProc->psProcDir);
+}
+#endif
+/*!
+******************************************************************************
+
+ @Function    : RemoveProcEntries
+
+ Description
+
+ Proc filesystem entry deletion - Remove all proc filesystem entries for
+ the driver.
+
+ @Input none
+
+ @Return nothing
+
+*****************************************************************************/
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+	RemoveProcEntrySeq( g_pProcDebugLevel );
+#ifdef PVR_MANUAL_POWER_CONTROL
+	RemoveProcEntrySeq( g_pProcPowerLevel );
+#endif /* PVR_MANUAL_POWER_CONTROL */
+#endif
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	RemoveProcEntrySeq(g_pProcQueue);
+#endif
+	RemoveProcEntrySeq(g_pProcVersion);
+	RemoveProcEntrySeq(g_pProcSysNodes);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+	while (dir->subdir)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+		RemoveProcEntry(dir->subdir->name);
+	}
+	remove_proc_entry(PVRProcDirRoot, NULL);
+#else
+	proc_remove(dir);
+#endif
+
+}
+
+/*************************************************************************/ /*!
+@Function PVRProcGetData
+@Description Extract data from PVR proc object.
+@Input pointer to pvr_proc_dir_entr object
+@Return pointer to data object passed in to Proc create function.
+*/ /**************************************************************************/
+void *PVRProcGetData(struct pvr_proc_dir_entry *ppde)
+{
+    return ppde->data;
+}
+
+/*****************************************************************************
+ FUNCTION	:	ProcSeqShowVersion
+
+ PURPOSE	:	Print the content of version to /proc file
+
+ PARAMETERS	:	sfile - /proc seq_file
+				el - Element to print
+*****************************************************************************/
+static void ProcSeqShowVersion(struct seq_file *sfile, void* el)
+{
+	SYS_DATA *psSysData;
+	IMG_CHAR *pszSystemVersionString = "None";
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf(sfile,
+				"Version %s (%s) %s\n",
+				PVRVERSION_STRING,
+				PVR_BUILD_TYPE, PVR_BUILD_DIR);
+		return;
+	}
+
+	psSysData = SysAcquireDataNoCheck();
+#if defined(SUPPORT_TI_VERSION_STRING)
+	if(psSysData != IMG_NULL && psSysData->szTIVersion != IMG_NULL)
+	{
+		seq_printf( sfile, "UM Services Version: %s\n",
+				psSysData->szTIVersion);
+	}
+#endif
+	if(psSysData != IMG_NULL && psSysData->pszVersionString != IMG_NULL)
+	{
+		pszSystemVersionString = psSysData->pszVersionString;
+	}
+
+	seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+    switch (deviceType)
+    {
+        default:
+        {
+            static IMG_CHAR text[10];
+
+            sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+            return text;
+        }
+    }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+    switch (deviceClass)
+    {
+	case PVRSRV_DEVICE_CLASS_3D:
+	{
+	    return "3D";
+	}
+	case PVRSRV_DEVICE_CLASS_DISPLAY:
+	{
+	    return "display";
+	}
+	case PVRSRV_DEVICE_CLASS_BUFFER:
+	{
+	    return "buffer";
+	}
+	default:
+	{
+	    static IMG_CHAR text[10];
+
+	    sprintf(text, "?%x", (IMG_UINT)deviceClass);
+	    return text;
+	}
+    }
+}
+
+static IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+	off_t *pOff = va_arg(va, off_t*);
+	if (--(*pOff))
+	{
+		return IMG_NULL;
+	}
+	else
+	{
+		return psNode;
+	}
+}
+
+/*****************************************************************************
+ FUNCTION	:	ProcSeqShowSysNodes
+
+ PURPOSE	:	Print the content of version to /proc file
+
+ PARAMETERS	:	sfile - /proc seq_file
+				el - Element to print
+*****************************************************************************/
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+	PVRSRV_DEVICE_NODE *psDevNode;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN)
+	{
+		seq_printf( sfile,
+						"Registered nodes\n"
+						"Addr     Type     Class    Index Ref pvDev     Size Res\n");
+		return;
+	}
+
+	psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+	seq_printf( sfile,
+			  "%p %-8s %-8s %4d  %2u  %p  %3u  %p\n",
+			  psDevNode,
+			  deviceTypeToString(psDevNode->sDevId.eDeviceType),
+			  deviceClassToString(psDevNode->sDevId.eDeviceClass),
+			  psDevNode->sDevId.eDeviceClass,
+			  psDevNode->ui32RefCount,
+			  psDevNode->pvDevice,
+			  psDevNode->ui32pvDeviceSize,
+			  psDevNode->hResManContext);
+}
+
+/*****************************************************************************
+ FUNCTION	:	ProcSeqOff2ElementSysNodes
+
+ PURPOSE	:	Transale offset to element (/proc stuff)
+
+ PARAMETERS	:	sfile - /proc seq_file
+				off - the offset into the buffer
+
+ RETURNS    :   element to print
+*****************************************************************************/
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+    SYS_DATA *psSysData;
+    PVRSRV_DEVICE_NODE*psDevNode = IMG_NULL;
+    
+    PVR_UNREFERENCED_PARAMETER(sfile);
+    
+    if(!off)
+    {
+	return PVR_PROC_SEQ_START_TOKEN;
+    }
+
+    psSysData = SysAcquireDataNoCheck();
+    if (psSysData != IMG_NULL)
+    {
+	/* Find Dev Node */
+	psDevNode = (PVRSRV_DEVICE_NODE*)
+			List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+													DecOffPsDev_AnyVaCb,
+													&off);
+    }
+
+    /* Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL */
+    return (void*)psDevNode;
+}
+
+/*****************************************************************************
+ End of file (proc.c)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/proc.h b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.h
new file mode 100644
index 0000000..e3abec2
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/proc.h
@@ -0,0 +1,95 @@
+/*************************************************************************/ /*!
+@Title          Proc interface definition.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Functions for creating and reading proc filesystem entries.
+                Refer to proc.c
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0))
+#include <asm/system.h>
+#endif
+#include <linux/seq_file.h>
+#include "img_defs.h"
+
+struct pvr_proc_dir_entry;
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef	int (pvr_proc_write_t)(struct file *file, const char __user *buffer,
+                               unsigned long count, void *data);
+
+IMG_INT CreateProcEntries(void);
+void RemoveProcEntries(void);
+
+struct pvr_proc_dir_entry* CreateProcReadEntrySeq(const IMG_CHAR* name,
+                                                  IMG_VOID* data,
+                                                  pvr_next_proc_seq_t next_handler,
+                                                  pvr_show_proc_seq_t show_handler,
+                                                  pvr_off2element_proc_seq_t off2element_handler,
+                                                  pvr_startstop_proc_seq_t startstop_handler);
+
+struct pvr_proc_dir_entry* CreateProcEntrySeq(const IMG_CHAR* name,
+                                              IMG_VOID* data,
+                                              pvr_next_proc_seq_t next_handler,
+                                              pvr_show_proc_seq_t show_handler,
+                                              pvr_off2element_proc_seq_t off2element_handler,
+                                              pvr_startstop_proc_seq_t startstop_handler,
+                                              pvr_proc_write_t whandler);
+
+struct pvr_proc_dir_entry* CreatePerProcessProcEntrySeq(const IMG_CHAR* name,
+                                                        IMG_VOID* data,
+                                                        pvr_next_proc_seq_t next_handler,
+                                                        pvr_show_proc_seq_t show_handler,
+                                                        pvr_off2element_proc_seq_t off2element_handler,
+                                                        pvr_startstop_proc_seq_t startstop_handler,
+                                                        pvr_proc_write_t whandler);
+
+void RemoveProcEntrySeq(struct pvr_proc_dir_entry* proc_entry);
+void RemovePerProcessProcEntrySeq(struct pvr_proc_dir_entry* proc_entry);
+
+void *PVRProcGetData(struct pvr_proc_dir_entry* ppde);
+
+#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
new file mode 100644
index 0000000..a637e96
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_bridge_k.c
@@ -0,0 +1,761 @@
+/*************************************************************************/ /*!
+@Title          PVR Bridge Module (kernel side)
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Receives calls from the user portion of services and
+                despatches them to functions in the kernel portion.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/fs.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "mutex.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+#include "pvr_uaccess.h"
+#include "refcount.h"
+#include "buffer_manager.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+/* VGX: */
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+/* SGX: */
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#define	PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define	PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+static struct pvr_proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#endif
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+IMG_UINT64 g_ui64MemInfoID;
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+	{
+		g_ProcBridgeStats = CreateProcReadEntrySeq(
+												  "bridge_stats", 
+												  NULL,
+												  ProcSeqNextBridgeStats,
+												  ProcSeqShowBridgeStats,
+												  ProcSeqOff2ElementBridgeStats,
+												  ProcSeqStartstopBridgeStats
+						  						 );
+		if(!g_ProcBridgeStats)
+		{
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		}
+	}
+#endif
+	return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+    RemoveProcEntrySeq(g_ProcBridgeStats);
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+/*
+ * Lock MMap regions list (called on page start/stop while reading /proc/mmap)
+ *
+ * sfile : seq_file that handles /proc file
+ * start : TRUE if it's start, FALSE if it's stop
+ *  
+ */
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start) 
+{
+	if(start) 
+	{
+		LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+	}
+	else
+	{
+		LinuxUnLockMutex(&gPVRSRVLock);
+	}
+}
+
+
+/*
+ * Convert offset (index from KVOffsetTable) to element 
+ * (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * off : index into the KVOffsetTable from which to print
+ *  
+ * returns void* : Pointer to element that will be dumped
+ *  
+*/
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+	if(!off) 
+	{
+		return PVR_PROC_SEQ_START_TOKEN;
+	}
+
+	if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+	{
+		return (void*)0;
+	}
+
+
+	return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+/*
+ * Gets next MMap element to show. (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ * off : index into the KVOffsetTable from which to print
+ *  
+ * returns void* : Pointer to element to show (0 ends iteration)
+*/
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+	return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+/*
+ * Show MMap element (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ *  
+*/
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+	PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = (	PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+	if(el == PVR_PROC_SEQ_START_TOKEN) 
+	{
+		seq_printf(sfile,
+						  "Total ioctl call count = %u\n"
+						  "Total number of bytes copied via copy_from_user = %u\n"
+						  "Total number of bytes copied via copy_to_user = %u\n"
+						  "Total number of bytes copied via copy_*_user = %u\n\n"
+						  "%-45s | %-40s | %10s | %20s | %10s\n",
+						  g_BridgeGlobalStats.ui32IOCTLCount,
+						  g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+						  g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+						  g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+						  "Bridge Name",
+						  "Wrapper Function",
+						  "Call Count",
+						  "copy_from_user Bytes",
+						  "copy_to_user Bytes"
+						 );
+		return;
+	}
+
+	seq_printf(sfile,
+				   "%-45s   %-40s   %-10u   %-20u   %-10u\n",
+				   psEntry->pszIOCName,
+				   psEntry->pszFunctionName,
+				   psEntry->ui32CallCount,
+				   psEntry->ui32CopyFromUserTotalBytes,
+				   psEntry->ui32CopyToUserTotalBytes);
+}
+#endif /* DEBUG_BRIDGE_KM */
+
+
+#if defined(SUPPORT_DRI_DRM)
+int
+PVRSRV_BridgeDispatchKM(struct drm_device unref__ *dev, void *arg, struct drm_file *pFile)
+#else
+long
+PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsigned long arg)
+#endif
+{
+	IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+	PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+	PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+	PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+	IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+	IMG_INT err = -EFAULT;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+#if defined(SUPPORT_DRI_DRM)
+	psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+	PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+	psBridgePackageKM = &sBridgePackageKM;
+
+	if(!OSAccessOK(PVR_VERIFY_WRITE,
+				   psBridgePackageUM,
+				   sizeof(PVRSRV_BRIDGE_PACKAGE)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+				 __FUNCTION__));
+
+		goto unlock_and_return;
+	}
+	
+	/* FIXME - Currently the CopyFromUserWrapper which collects stats about
+	 * how much data is shifted to/from userspace isn't available to us
+	 * here. */
+	if(OSCopyFromUser(IMG_NULL,
+					  psBridgePackageKM,
+					  psBridgePackageUM,
+					  sizeof(PVRSRV_BRIDGE_PACKAGE))
+	  != PVRSRV_OK)
+	{
+		goto unlock_and_return;
+	}
+#endif
+
+	cmd = psBridgePackageKM->ui32BridgeID;
+	
+	if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+	{
+		PVRSRV_ERROR eError;
+
+		eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+									(IMG_PVOID *)&psPerProc,
+									psBridgePackageKM->hKernelServices,
+									PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+					 __FUNCTION__, eError));
+			goto unlock_and_return;
+		}
+
+		if(psPerProc->ui32PID != ui32PID)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+					 "belonging to process %d", __FUNCTION__, ui32PID,
+					 psPerProc->ui32PID));
+			goto unlock_and_return;
+		}
+	}
+	else
+	{
+		/* lookup per-process data for this process */
+		psPerProc = PVRSRVPerProcessData(ui32PID);
+		if(psPerProc == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+					 "Couldn't create per-process data area"));
+			goto unlock_and_return;
+		}
+	}
+
+	psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+	switch(cmd)
+	{
+		case PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2:
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
+						 "per file descriptor", __FUNCTION__));
+				err = -EINVAL;
+				goto unlock_and_return;
+			}
+			break;
+		}
+
+		case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2:
+		{
+			PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
+				(PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)(IMG_UINTPTR_T)psBridgePackageKM->hParamIn;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(!psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
+						 "associated MemInfo handle", __FUNCTION__));
+				err = -EINVAL;
+				goto unlock_and_return;
+			}
+
+			if (pvr_put_user(psPrivateData->hKernelMemInfo, &psMapDevMemIN->hKernelMemInfo) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+			break;
+		}
+
+		default:
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
+						 "to use privileged service", __FUNCTION__));
+				goto unlock_and_return;
+			}
+			break;
+		}
+	}
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+	switch(cmd)
+	{
+		case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+		case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+			int authenticated = pFile->authenticated;
+			PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+			if (authenticated)
+			{
+				break;
+			}
+
+			/*
+			 * The DRM file structure we are using for Services
+			 * is not one that DRI authentication was done on.
+			 * Look for an authenticated file structure for
+			 * this process, making sure the DRM master is the
+			 * same as ours.
+			 */
+			psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+			if (psEnvPerProc == IMG_NULL)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+
+			list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+			{
+				struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+				if (pFile->master == psDRMFile->master)
+				{
+					authenticated |= psDRMFile->authenticated;
+					if (authenticated)
+					{
+						break;
+					}
+				}
+			}
+
+			if (!authenticated)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+				err = -EPERM;
+				goto unlock_and_return;
+			}
+			break;
+		}
+		default:
+			break;
+	}
+#endif /* defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) */
+
+	err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+	if(err != PVRSRV_OK)
+		goto unlock_and_return;
+
+	switch(cmd)
+	{
+		case PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2:
+		{
+			PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
+				(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)(IMG_UINTPTR_T)psBridgePackageKM->hParamOut;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+			IMG_HANDLE hMemInfo;
+			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+			if (pvr_get_user(hMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+
+			/* Look up the meminfo we just exported */
+			if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+								  (IMG_PVOID *)&psKernelMemInfo,
+								  hMemInfo,
+								  PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+
+			/* Bump the refcount; decremented on release of the fd */
+			PVRSRVKernelMemInfoIncRef(psKernelMemInfo);
+
+			/* Tell the XProc about the export if required */
+			if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+			{
+				BM_XProcIndexAcquire(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+			}
+
+			psPrivateData->hKernelMemInfo = hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+			psPrivateData->ui64Stamp = ++g_ui64MemInfoID;
+
+			psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp;
+			if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+#endif
+			break;
+		}
+
+#if defined(SUPPORT_MEMINFO_IDS)
+		case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+		case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2:
+		{
+			PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+				(PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)(IMG_UINTPTR_T)psBridgePackageKM->hParamOut;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+			if (pvr_put_user(psPrivateData->ui64Stamp, &psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+			break;
+		}
+
+		case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+		{
+			PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+				(PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)(IMG_UINTPTR_T)psBridgePackageKM->hParamOut;
+			if (pvr_put_user(++g_ui64MemInfoID, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+			break;
+		}
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
+
+		default:
+			break;
+	}
+
+unlock_and_return:
+	LinuxUnLockMutex(&gPVRSRVLock);
+	return err;
+}
+
+#if defined(CONFIG_COMPAT)
+#if defined(SUPPORT_DRI_DRM)
+int
+PVRSRV_BridgeCompatDispatchKM(struct drm_device unref__ *dev, void *arg, struct drm_file *pFile)
+#else
+long PVRSRV_BridgeCompatDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsigned long arg)
+#endif
+{
+	struct bridge_package_from_32
+	{
+		IMG_UINT32	bridge_id;              /*!< ioctl bridge group */
+		IMG_UINT32	size;                   /*!< size of structure */
+		IMG_UINT64	addr_param_in;          /*!< input data buffer */
+		IMG_UINT64	addr_param_out;         /*!< output data buffer */
+		IMG_UINT32	in_buffer_size;         /*!< size of input data buffer */
+		IMG_UINT32	out_buffer_size;        /*!< size of output data buffer */
+		IMG_UINT64	hKernelServices;        /*!< kernel servcies handle */
+	};
+
+#if !defined(SUPPORT_DRI_DRM)
+	struct bridge_package_from_32 params;
+	struct bridge_package_from_32 * const params_addr = &params;
+#endif
+	PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+	PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+	IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+	PVRSRV_PER_PROCESS_DATA *psPerProc;
+	IMG_INT err = -EFAULT;
+ 
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+#if defined(SUPPORT_DRI_DRM)
+	sBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE)(*(PVRSRV_BRIDGE_PACKAGE*)arg);
+	psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+	PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+	if(!OSAccessOK(PVR_VERIFY_READ, (void *) arg, sizeof(struct bridge_package_from_32)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments", __FUNCTION__));
+		goto unlock_and_return;
+	}
+
+	if(OSCopyFromUser(NULL, params_addr, (void*) arg, sizeof(struct bridge_package_from_32))
+		!= PVRSRV_OK)
+	{
+		goto unlock_and_return;
+	}
+    
+	sBridgePackageKM.ui32BridgeID = PVRSRV_GET_BRIDGE_ID(params_addr->bridge_id);
+	sBridgePackageKM.ui32Size = sizeof(sBridgePackageKM);
+	sBridgePackageKM.hParamIn = (IMG_HANDLE) ((IMG_UINTPTR_T) params_addr->addr_param_in);
+	sBridgePackageKM.hParamOut = (IMG_HANDLE) ((IMG_UINTPTR_T) params_addr->addr_param_out);
+	sBridgePackageKM.ui32InBufferSize = params_addr->in_buffer_size;
+	sBridgePackageKM.ui32OutBufferSize = params_addr->out_buffer_size;
+	sBridgePackageKM.hKernelServices = (IMG_HANDLE) ((IMG_SIZE_T) params_addr->hKernelServices);
+            
+	psBridgePackageKM = &sBridgePackageKM;
+#endif
+	if(sBridgePackageKM.ui32BridgeID != PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES))
+	{
+		PVRSRV_ERROR eError;
+
+		eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+									(IMG_PVOID *)&psPerProc,
+									psBridgePackageKM->hKernelServices,
+									PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+		if(eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+					 __FUNCTION__, eError));
+			goto unlock_and_return;
+		}
+
+		if(psPerProc->ui32PID != ui32PID)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+					 "belonging to process %d", __FUNCTION__, ui32PID,
+					 psPerProc->ui32PID));
+			goto unlock_and_return;
+		}
+	}
+	else
+	{
+		/* lookup per-process data for this process */
+		psPerProc = PVRSRVPerProcessData(ui32PID);
+		if(psPerProc == IMG_NULL)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+					 "Couldn't create per-process data area"));
+			goto unlock_and_return;
+		}
+	}
+
+	switch(sBridgePackageKM.ui32BridgeID)
+	{
+		case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2):
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
+						 "per file descriptor", __FUNCTION__));
+				err = -EINVAL;
+				goto unlock_and_return;
+			}
+			break;
+		}
+
+		case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEV_MEMORY_2):
+		{
+			PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
+				(PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)(IMG_UINTPTR_T)psBridgePackageKM->hParamIn;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(!psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
+						 "associated MemInfo handle", __FUNCTION__));
+				err = -EINVAL;
+				goto unlock_and_return;
+			}
+
+			if (pvr_put_user(psPrivateData->hKernelMemInfo, &psMapDevMemIN->hKernelMemInfo) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+			break;
+		}
+
+		default:
+		{
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+			if(psPrivateData->hKernelMemInfo)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
+						 "to use privileged service", __FUNCTION__));
+				goto unlock_and_return;
+			}
+			break;
+		}
+	}
+
+	err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+	if(err != PVRSRV_OK)
+		goto unlock_and_return;
+
+	switch(sBridgePackageKM.ui32BridgeID)
+	{
+		case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2):
+		{
+			PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
+				(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)(IMG_UINTPTR_T)psBridgePackageKM->hParamOut;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+			IMG_HANDLE hMemInfo;
+			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+			if (pvr_get_user(hMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+
+			/* Look up the meminfo we just exported */
+			if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+								  (IMG_PVOID *)&psKernelMemInfo,
+								  hMemInfo,
+								  PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+
+			/* Bump the refcount; decremented on release of the fd */
+			PVRSRVKernelMemInfoIncRef(psKernelMemInfo);
+
+			/* Tell the XProc about the export if required */
+			if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+			{
+				BM_XProcIndexAcquire(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+			}
+
+			psPrivateData->hKernelMemInfo = hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+			psPrivateData->ui64Stamp = ++g_ui64MemInfoID;
+
+			psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp;
+			if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+#endif
+			break;
+		}
+
+#if defined(SUPPORT_MEMINFO_IDS)
+		case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEV_MEMORY):
+		case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEV_MEMORY_2):
+		{
+			PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+				(PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)(IMG_UINTPTR_T)psBridgePackageKM->hParamOut;
+			PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+			if (pvr_put_user(psPrivateData->ui64Stamp, &psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+			break;
+		}
+
+		case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY):
+		{
+			PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+				(PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)(IMG_UINTPTR_T)psBridgePackageKM->hParamOut;
+			if (pvr_put_user(++g_ui64MemInfoID, &psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp) != 0)
+			{
+				err = -EFAULT;
+				goto unlock_and_return;
+			}
+			break;
+		}
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
+
+		default:
+			break;
+	}
+
+unlock_and_return:
+	LinuxUnLockMutex(&gPVRSRVLock);
+	return err;
+}
+#endif /* defined(CONFIG_COMPAT) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_counting_timeline.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_counting_timeline.c
new file mode 100644
index 0000000..c0485a1
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_counting_timeline.c
@@ -0,0 +1,158 @@
+/*************************************************************************/ /*!
+@File
+@Title          PowerVR Linux software "counting" timeline fence implementation
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/kref.h>
+#include <linux/sync_file.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "servicesext.h"
+#include "pvr_counting_timeline.h"
+#include "pvr_sw_fence.h"
+
+struct PVR_COUNTING_FENCE_TIMELINE {
+	char name[32];
+	struct PVR_SW_FENCE_CONTEXT *psSwFenceCtx;
+
+	spinlock_t sActive_fences_lock;
+	IMG_UINT64 ui64Current_value; /* guarded by active_fences_lock */
+	struct list_head sActive_fences;
+
+	struct kref sRef;
+};
+
+struct PVR_COUNTING_FENCE {
+	IMG_UINT64 ui64Value;
+	struct dma_fence *psFence;
+	struct list_head sActive_list_entry;
+};
+
+struct PVR_COUNTING_FENCE_TIMELINE *pvr_counting_fence_timeline_create(const char *name)
+{
+	struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline = kmalloc(sizeof(*psFenceTimeline), GFP_KERNEL);
+
+	if (!psFenceTimeline)
+		goto err_out;
+
+	strlcpy(psFenceTimeline->name, name, sizeof(psFenceTimeline->name));
+
+	psFenceTimeline->psSwFenceCtx = pvr_sw_fence_context_create(psFenceTimeline->name, "pvr_sw_sync");
+	if (!psFenceTimeline->psSwFenceCtx)
+		goto err_free_timeline;
+
+	psFenceTimeline->ui64Current_value = 0;
+	kref_init(&psFenceTimeline->sRef);
+	spin_lock_init(&psFenceTimeline->sActive_fences_lock);
+	INIT_LIST_HEAD(&psFenceTimeline->sActive_fences);
+
+err_out:
+	return psFenceTimeline;
+
+err_free_timeline:
+	kfree(psFenceTimeline);
+	psFenceTimeline = NULL;
+	goto err_out;
+}
+
+void pvr_counting_fence_timeline_force_complete(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline)
+{
+	struct list_head *entry, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&psFenceTimeline->sActive_fences_lock, flags);
+
+	list_for_each_safe(entry, tmp, &psFenceTimeline->sActive_fences)
+	{
+		struct PVR_COUNTING_FENCE *psPvrCountingFence = list_entry(entry, struct PVR_COUNTING_FENCE, sActive_list_entry);
+		dma_fence_signal(psPvrCountingFence->psFence);
+		dma_fence_put(psPvrCountingFence->psFence);
+		psPvrCountingFence->psFence = NULL;
+		list_del(&psPvrCountingFence->sActive_list_entry);
+		kfree(psPvrCountingFence);
+	}
+	spin_unlock_irqrestore(&psFenceTimeline->sActive_fences_lock, flags);
+}
+
+static void pvr_counting_fence_timeline_destroy(struct kref *kref)
+{
+	struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline = container_of(kref, struct PVR_COUNTING_FENCE_TIMELINE, sRef);
+
+	WARN_ON(!list_empty(&psFenceTimeline->sActive_fences));
+
+	pvr_sw_fence_context_destroy(psFenceTimeline->psSwFenceCtx);
+	kfree(psFenceTimeline);
+}
+
+void pvr_counting_fence_timeline_put(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline)
+{
+	kref_put(&psFenceTimeline->sRef, pvr_counting_fence_timeline_destroy);
+}
+
+struct PVR_COUNTING_FENCE_TIMELINE *pvr_counting_fence_timeline_get(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline)
+{
+	if (!psFenceTimeline)
+		return NULL;
+	kref_get(&psFenceTimeline->sRef);
+	return psFenceTimeline;
+}
+
+struct dma_fence *pvr_counting_fence_create(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline, IMG_UINT64 ui64Value)
+{
+	unsigned long flags;
+	struct dma_fence *psSwFence;
+	struct PVR_COUNTING_FENCE *psCountFence = kmalloc(sizeof(*psCountFence), GFP_KERNEL);
+
+	if (!psCountFence)
+		return NULL;
+
+	psSwFence = pvr_sw_fence_create(psFenceTimeline->psSwFenceCtx);
+	if (!psSwFence)
+		goto err_free_fence;
+
+	psCountFence->psFence = dma_fence_get(psSwFence);
+	psCountFence->ui64Value = ui64Value;
+
+	spin_lock_irqsave(&psFenceTimeline->sActive_fences_lock, flags);
+
+	list_add_tail(&psCountFence->sActive_list_entry, &psFenceTimeline->sActive_fences);
+
+	spin_unlock_irqrestore(&psFenceTimeline->sActive_fences_lock, flags);
+
+	return psSwFence;
+
+err_free_fence:
+	kfree(psCountFence);
+	return NULL;
+}
+
+void pvr_counting_fence_timeline_inc(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline, IMG_UINT64 ui64Value)
+{
+	struct list_head *entry, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&psFenceTimeline->sActive_fences_lock, flags);
+
+	psFenceTimeline->ui64Current_value += ui64Value;
+
+	list_for_each_safe(entry, tmp, &psFenceTimeline->sActive_fences)
+	{
+		struct PVR_COUNTING_FENCE *psCountFence = list_entry(entry, struct PVR_COUNTING_FENCE, sActive_list_entry);
+		if (psCountFence->ui64Value <= psFenceTimeline->ui64Current_value)
+		{
+			dma_fence_signal(psCountFence->psFence);
+			dma_fence_put(psCountFence->psFence);
+			psCountFence->psFence = NULL;
+			list_del(&psCountFence->sActive_list_entry);
+			kfree(psCountFence);
+		}
+	}
+
+	spin_unlock_irqrestore(&psFenceTimeline->sActive_fences_lock, flags);
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_counting_timeline.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_counting_timeline.h
new file mode 100644
index 0000000..b8e2d96
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_counting_timeline.h
@@ -0,0 +1,25 @@
+/*************************************************************************/ /*!
+@File
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#if !defined(__PVR_COUNTING_TIMELINE_H__)
+#define __PVR_COUNTING_TIMELINE_H__
+
+struct PVR_COUNTING_FENCE_TIMELINE;
+
+struct PVR_COUNTING_FENCE_TIMELINE *pvr_counting_fence_timeline_create(const char *name);
+
+void pvr_counting_fence_timeline_put(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline);
+
+struct PVR_COUNTING_FENCE_TIMELINE *pvr_counting_fence_timeline_get(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline);
+
+struct dma_fence *pvr_counting_fence_create(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline, u64 value);
+
+void pvr_counting_fence_timeline_inc(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline, u64 value);
+
+void pvr_counting_fence_timeline_force_complete(struct PVR_COUNTING_FENCE_TIMELINE *psFenceTimeline);
+
+#endif /* !defined(__PVR_COUNTING_TIMELINE_H__) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c
new file mode 100644
index 0000000..621a30d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_debug.c
@@ -0,0 +1,522 @@
+/*************************************************************************/ /*!
+@Title          Debug Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provides kernel side Debug Functionality
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>			// strncpy, strlen
+#include <stdarg.h>
+#include <linux/seq_file.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "mutex.h"
+#include "linkage.h"
+#include "pvr_uaccess.h"
+
+#if !defined(CONFIG_PREEMPT)
+#define	PVR_DEBUG_ALWAYS_USE_SPINLOCK
+#endif
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+/******** BUFFERED LOG MESSAGES ********/
+
+/* Because we don't want to have to handle CCB wrapping, each buffered
+ * message is rounded up to PVRSRV_DEBUG_CCB_MESG_MAX bytes. This means
+ * there is the same fixed number of messages that can be stored,
+ * regardless of message length.
+ */
+
+#if defined(PVRSRV_DEBUG_CCB_MAX)
+
+#define PVRSRV_DEBUG_CCB_MESG_MAX	PVR_MAX_DEBUG_MESSAGE_LEN
+
+#include <linux/syscalls.h>
+#include <linux/time.h>
+
+typedef struct
+{
+	const IMG_CHAR *pszFile;
+	IMG_INT iLine;
+	IMG_UINT32 ui32TID;
+	IMG_CHAR pcMesg[PVRSRV_DEBUG_CCB_MESG_MAX];
+	struct timeval sTimeVal;
+}
+PVRSRV_DEBUG_CCB;
+
+static PVRSRV_DEBUG_CCB gsDebugCCB[PVRSRV_DEBUG_CCB_MAX] = { { 0 } };
+
+static IMG_UINT giOffset = 0;
+
+static PVRSRV_LINUX_MUTEX gsDebugCCBMutex;
+
+static void
+AddToBufferCCB(const IMG_CHAR *pszFileName, IMG_UINT32 ui32Line,
+			   const IMG_CHAR *szBuffer)
+{
+	LinuxLockMutex(&gsDebugCCBMutex);
+
+	gsDebugCCB[giOffset].pszFile = pszFileName;
+	gsDebugCCB[giOffset].iLine   = ui32Line;
+	gsDebugCCB[giOffset].ui32TID = current->tgid;
+
+	do_gettimeofday(&gsDebugCCB[giOffset].sTimeVal);
+
+	strncpy(gsDebugCCB[giOffset].pcMesg, szBuffer, PVRSRV_DEBUG_CCB_MESG_MAX - 1);
+	gsDebugCCB[giOffset].pcMesg[PVRSRV_DEBUG_CCB_MESG_MAX - 1] = 0;
+
+	giOffset = (giOffset + 1) % PVRSRV_DEBUG_CCB_MAX;
+
+	LinuxUnLockMutex(&gsDebugCCBMutex);
+}
+
+IMG_EXPORT IMG_VOID PVRSRVDebugPrintfDumpCCB(void)
+{
+	int i;
+
+	LinuxLockMutex(&gsDebugCCBMutex);
+	
+	for(i = 0; i < PVRSRV_DEBUG_CCB_MAX; i++)
+	{
+		PVRSRV_DEBUG_CCB *psDebugCCBEntry =
+			&gsDebugCCB[(giOffset + i) % PVRSRV_DEBUG_CCB_MAX];
+
+		/* Early on, we won't have PVRSRV_DEBUG_CCB_MAX messages */
+		if(!psDebugCCBEntry->pszFile)
+			continue;
+
+		printk("%s:%d:\t[%5ld.%6ld] %s\n",
+			   psDebugCCBEntry->pszFile,
+			   psDebugCCBEntry->iLine,
+			   (long)psDebugCCBEntry->sTimeVal.tv_sec,
+			   (long)psDebugCCBEntry->sTimeVal.tv_usec,
+			   psDebugCCBEntry->pcMesg);
+	}
+
+	LinuxUnLockMutex(&gsDebugCCBMutex);
+}
+
+#else /* defined(PVRSRV_DEBUG_CCB_MAX) */
+static INLINE void
+AddToBufferCCB(const IMG_CHAR *pszFileName, IMG_UINT32 ui32Line,
+               const IMG_CHAR *szBuffer)
+{
+	(void)pszFileName;
+	(void)szBuffer;
+	(void)ui32Line;
+}
+
+IMG_EXPORT IMG_VOID PVRSRVDebugPrintfDumpCCB(void)
+{
+	/* Not available */
+}
+
+#endif /* defined(PVRSRV_DEBUG_CCB_MAX) */
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+						 const IMG_CHAR* pszFormat, va_list VArgs)
+						 IMG_FORMAT_PRINTF(3, 0);
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+/* NOTE: Must NOT be static! Used in module.c.. */
+IMG_UINT32 gPVRDebugLevel =
+	(DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING | DBGPRIV_BUFFERED);
+
+#endif /* defined(PVRSRV_NEED_PVR_DPF) || defined(PVRSRV_NEED_PVR_TRACE) */
+
+#define	PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+/* Message buffer for non-IRQ messages */
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+#endif
+
+/* Message buffer for IRQ messages */
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+/* The lock is used to control access to gszBufferNonIRQ */
+static PVRSRV_LINUX_MUTEX gsDebugMutexNonIRQ;
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to gszBufferIRQ */
+/* PRQA S 0671,0685 1 */ /* ignore warnings about C99 style initialisation */
+static spinlock_t gsDebugLockIRQ = SPIN_LOCK_UNLOCKED;
+#else
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+#endif
+
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+#if !defined (USE_SPIN_LOCK) /* to keep QAC happy */ 
+#define	USE_SPIN_LOCK (in_interrupt() || !preemptible())
+#endif
+#endif
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+	if (USE_SPIN_LOCK)
+#endif
+	{
+		spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+	}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+	else
+	{
+		LinuxLockMutexNested(&gsDebugMutexNonIRQ, PVRSRV_LOCK_CLASS_PVR_DEBUG);
+	}
+#endif
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+	if (USE_SPIN_LOCK)
+#endif
+	{
+		spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+	}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+	else
+	{
+		LinuxUnLockMutex(&gsDebugMutexNonIRQ);
+	}
+#endif
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+	if (USE_SPIN_LOCK)
+#endif
+	{
+		*ppszBuf = gszBufferIRQ;
+		*pui32BufSiz = sizeof(gszBufferIRQ);
+	}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+	else
+	{
+		*ppszBuf = gszBufferNonIRQ;
+		*pui32BufSiz = sizeof(gszBufferNonIRQ);
+	}
+#endif
+}
+
+/*
+ * Append a string to a buffer using formatted conversion.
+ * The function takes a variable number of arguments, pointed
+ * to by the var args list.
+ */
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+	IMG_UINT32 ui32Used;
+	IMG_UINT32 ui32Space;
+	IMG_INT32 i32Len;
+
+	ui32Used = strlen(pszBuf);
+	BUG_ON(ui32Used >= ui32BufSiz);
+	ui32Space = ui32BufSiz - ui32Used;
+
+	i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+	pszBuf[ui32BufSiz - 1] = 0;
+
+	/* Return true if string was truncated */
+	return (i32Len < 0 || i32Len >= (IMG_INT32)ui32Space) ? IMG_TRUE : IMG_FALSE;
+}
+
+/* Actually required for ReleasePrintf too */
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+	LinuxInitMutex(&gsDebugMutexNonIRQ);
+#endif
+#if defined(PVRSRV_DEBUG_CCB_MAX)
+	LinuxInitMutex(&gsDebugCCBMutex);
+#endif
+}
+
+/*!
+******************************************************************************
+	@Function    PVRSRVReleasePrintf
+	@Description To output an important message to the user in release builds
+	@Input       pszFormat - The message format string
+	@Input       ... - Zero or more arguments for use by the format string
+	@Return      None
+ ******************************************************************************/
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+	va_list vaArgs;
+	unsigned long ulLockFlags = 0;
+	IMG_CHAR *pszBuf;
+	IMG_UINT32 ui32BufSiz;
+
+	SelectBuffer(&pszBuf, &ui32BufSiz);
+
+	va_start(vaArgs, pszFormat);
+
+	GetBufferLock(&ulLockFlags);
+	strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+	if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+	{
+		printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+	}
+	else
+	{
+		printk(KERN_INFO "%s\n", pszBuf);
+	}
+
+	ReleaseBufferLock(ulLockFlags);
+	va_end(vaArgs);
+}
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+/*!
+******************************************************************************
+	@Function    PVRTrace
+	@Description To output a debug message to the user
+	@Input       pszFormat - The message format string
+	@Input       ... - Zero or more arguments for use by the format string
+	@Return      None
+ ******************************************************************************/
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+	va_list VArgs;
+	unsigned long ulLockFlags = 0;
+	IMG_CHAR *pszBuf;
+	IMG_UINT32 ui32BufSiz;
+
+	SelectBuffer(&pszBuf, &ui32BufSiz);
+
+	va_start(VArgs, pszFormat);
+
+	GetBufferLock(&ulLockFlags);
+
+	strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+	if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+	{
+		printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+	}
+	else
+	{
+		printk(KERN_INFO "%s\n", pszBuf);
+	}
+
+	ReleaseBufferLock(ulLockFlags);
+
+	va_end(VArgs);
+}
+
+#endif /* defined(PVRSRV_NEED_PVR_TRACE) */
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+/*!
+******************************************************************************
+	@Function    PVRSRVDebugPrintf
+	@Description To output a debug message to the user
+	@Input       uDebugLevel - The current debug level
+	@Input       pszFile - The source file generating the message
+	@Input       uLine - The line of the source file
+	@Input       pszFormat - The message format string
+	@Input       ... - Zero or more arguments for use by the format string
+	@Return      None
+ ******************************************************************************/
+IMG_VOID PVRSRVDebugPrintf	(
+						IMG_UINT32	ui32DebugLevel,
+						const IMG_CHAR*	pszFullFileName,
+						IMG_UINT32	ui32Line,
+						const IMG_CHAR*	pszFormat,
+						...
+					)
+{
+	IMG_BOOL bTrace;
+	const IMG_CHAR *pszFileName = pszFullFileName;
+
+	bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+	if (gPVRDebugLevel & ui32DebugLevel)
+	{
+		va_list vaArgs;
+		unsigned long ulLockFlags = 0;
+		IMG_CHAR *pszBuf;
+		IMG_UINT32 ui32BufSiz;
+
+		SelectBuffer(&pszBuf, &ui32BufSiz);
+
+		va_start(vaArgs, pszFormat);
+
+		GetBufferLock(&ulLockFlags);
+
+		/* Add in the level of warning */
+		if (bTrace == IMG_FALSE)
+		{
+			switch(ui32DebugLevel)
+			{
+				case DBGPRIV_FATAL:
+				{
+					strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_ERROR:
+				{
+					strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_WARNING:
+				{
+					strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_MESSAGE:
+				{
+					strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_VERBOSE:
+				{
+					strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+					break;
+				}
+				case DBGPRIV_BUFFERED:
+				{
+					strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+					break;
+				}
+				default:
+				{
+					strncpy (pszBuf, "PVR_K:(Unknown message level): ", (ui32BufSiz -1));
+					break;
+				}
+			}
+		}
+		else
+		{
+			strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+		}
+
+		if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+		{
+			printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+		}
+		else
+		{
+			if (ui32DebugLevel & DBGPRIV_BUFFERED)
+			{
+				/* We don't need the full path here */
+				const IMG_CHAR *pszShortName = strrchr(pszFileName, '/') + 1;
+				if(pszShortName)
+					pszFileName = pszShortName;
+
+				AddToBufferCCB(pszFileName, ui32Line, pszBuf);
+			}
+			else
+			{
+				printk(KERN_INFO "%s\n", pszBuf);
+			}
+		}
+
+		ReleaseBufferLock(ulLockFlags);
+
+		va_end (vaArgs);
+	}
+}
+
+#endif /* PVRSRV_NEED_PVR_DPF */
+
+#if defined(DEBUG)
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define	_PROC_SET_BUFFER_SZ		6
+	IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+	PVR_UNREFERENCED_PARAMETER(file);
+	PVR_UNREFERENCED_PARAMETER(data);
+
+	if (count > _PROC_SET_BUFFER_SZ)
+	{
+		return -EINVAL;
+	}
+	else
+	{
+		if (pvr_copy_from_user(data_buffer, buffer, count))
+			return -EINVAL;
+		if (data_buffer[count - 1] != '\n')
+			return -EINVAL;
+		if (sscanf(data_buffer, "%u", &gPVRDebugLevel) == 0)
+			return -EINVAL;
+		gPVRDebugLevel &= (1 << DBGPRIV_DBGLEVEL_COUNT) - 1;
+	}
+	return (count);
+}
+
+void ProcSeqShowDebugLevel(struct seq_file *sfile, void* el)
+{
+	PVR_UNREFERENCED_PARAMETER(el);
+
+	seq_printf(sfile, "%u\n", gPVRDebugLevel);
+}
+
+#endif /* defined(DEBUG) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c
new file mode 100644
index 0000000..9e6b92c
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c
@@ -0,0 +1,808 @@
+/*************************************************************************/ /*!
+@Title          PowerVR drm driver
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    linux module setup
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mm.h"
+#include "mmap.h"
+#include "mutex.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "pvr_bridge.h"
+#include "pvrmodule.h"
+#include "pvrversion.h"
+#include "lock.h"
+#include "linkage.h"
+#include "pvr_drm.h"
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+#include "pvr_drm_mod.h"
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))
+#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
+#endif
+
+#if (defined(PVR_LDM_PLATFORM_PRE_REGISTERED) || defined(PVR_LDM_DEVICE_TREE)) && !defined(NO_HARDWARE)
+#define PVR_USE_PRE_REGISTERED_PLATFORM_DEV
+#endif
+
+#if defined(PVR_LDM_DEVICE_TREE) && !defined(NO_HARDWARE)
+#define PVR_USE_DEVICE_TREE
+#endif
+
+#if (defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)) || defined(NO_HARDWARE)
+#define PVR_DRM_NAME	SYS_SGX_DEV_NAME
+#else
+#define PVR_DRM_NAME	PVRSRV_MODNAME
+#endif
+
+#define PVR_DRM_DESC	"Imagination Technologies PVR DRM"
+
+#define	PVR_DRM_DATE	"20110701"
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#define PVR_NEW_STYLE_DRM_PLATFORM_DEV
+#else
+#define PVR_OLD_STYLE_DRM_PLATFORM_DEV
+#endif
+#endif
+
+/*
+ * Prior to Linux 2.6.36, we couldn't do the release processing in post close
+ * when workqueues were being used, because drm_release held the big kernel
+ * lock (BKL) when it called post close.
+ * If the resman needs to wait for processing being done by a workqueue,
+ * that processing won't complete whilst the lock is held by another thread,
+ * as the workqueue won't get scheduled.
+ */
+#undef	PVR_DRI_DRM_USE_POST_CLOSE
+#if (defined(SUPPORT_DRI_DRM_EXT) && !defined(PVR_LINUX_USING_WORKQUEUES)) || \
+	(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+#define	PVR_DRI_DRM_USE_POST_CLOSE
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
+#define PVR_DRM_DRIVER_RENDER	DRIVER_RENDER
+#define PVR_DRM_RENDER_ALLOW	DRM_RENDER_ALLOW
+#else
+#define PVR_DRM_DRIVER_RENDER	0
+#define PVR_DRM_RENDER_ALLOW	0
+#endif
+
+DECLARE_WAIT_QUEUE_HEAD(sWaitForInit);
+
+#if defined(SUPPORT_DRM_MODESET)
+static struct drm_driver sPVRDrmDriver;
+#endif
+
+/* Once bInitComplete and bInitFailed are set, they stay set */
+IMG_BOOL bInitComplete;
+IMG_BOOL bInitFailed;
+
+#if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+static struct platform_device *psPlatDev;
+#endif
+struct platform_device *gpsPVRLDMDev;
+#else
+struct pci_dev *gpsPVRLDMDev;
+#endif
+#endif
+
+struct drm_device *gpsPVRDRMDev;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+#error "Linux kernel version 2.6.25 or later required for PVR DRM support"
+#endif
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if !defined(SUPPORT_DRI_DRM_EXT) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_USE_DEVICE_TREE)
+static struct of_device_id asPlatIdList[] = {
+	{
+		.compatible = SYS_SGX_DEV_NAME
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of,  asPlatIdList);
+#else
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+static struct platform_device_id asPlatIdList[] = {
+	{SYS_SGX_DEV_NAME, 0},
+	{}
+};
+#else	/* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+static struct pci_device_id asPciIdList[] = {
+#if defined(PVR_DRI_DRM_NOT_PCI)
+	{1, 1, 1, 1, 0, 0, 0},
+#else	/* defined(PVR_DRI_DRM_NOT_PCI) */
+	{SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#if defined(SYS_SGX_DEV1_DEVICE_ID)
+	{SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif	/* defined(SYS_SGX_DEV1_DEVICE_ID) */
+#endif	/* defined(PVR_DRI_DRM_NOT_PCI) */
+	{0}
+};
+#endif	/* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+#endif	/* defined(PVR_DEVICE_TREE) */
+#endif	/* !defined(SUPPORT_DRI_DRM_EXT) */
+
+struct device *
+PVRLDMGetDevice(void)
+{
+	return gpsPVRDRMDev->dev;
+}
+
+DRI_DRM_STATIC int
+PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
+{
+	int iRes = 0;
+
+	PVR_TRACE(("PVRSRVDrmLoad"));
+
+	gpsPVRDRMDev = dev;
+#if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+	gpsPVRLDMDev = dev->platformdev;
+#else
+	gpsPVRLDMDev = dev->pdev;
+#endif
+#endif
+
+#if defined(PDUMP)
+	iRes = dbgdrv_init();
+	if (iRes != 0)
+	{
+		goto exit;
+	}
+#endif
+	/* Module initialisation */
+	iRes = PVRCore_Init();
+	if (iRes != 0)
+	{
+		goto exit_dbgdrv_cleanup;
+	}
+
+#if defined(DISPLAY_CONTROLLER)
+	iRes = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+	if (iRes != 0)
+	{
+		goto exit_pvrcore_cleanup;
+	}
+#endif
+	goto exit;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+	PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+	dbgdrv_cleanup();
+#endif
+exit:
+	if (iRes != 0)
+	{
+		bInitFailed = IMG_TRUE;
+	}
+	bInitComplete = IMG_TRUE;
+
+	wake_up_interruptible(&sWaitForInit);
+
+	return iRes;
+}
+
+DRI_DRM_STATIC int
+PVRSRVDrmUnload(struct drm_device *dev)
+{
+	PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+	PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+	PVRCore_Cleanup();
+
+#if defined(PDUMP)
+	dbgdrv_cleanup();
+#endif
+
+	return 0;
+}
+
+DRI_DRM_STATIC int
+PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+	while (!bInitComplete)
+	{
+		DEFINE_WAIT(sWait);
+
+		prepare_to_wait(&sWaitForInit, &sWait, TASK_INTERRUPTIBLE);
+
+		if (!bInitComplete)
+		{
+			PVR_TRACE(("%s: Waiting for module initialisation to complete", __FUNCTION__));
+
+			schedule();
+		}
+
+		finish_wait(&sWaitForInit, &sWait);
+
+		if (signal_pending(current))
+		{
+			return -ERESTARTSYS;
+		}
+	}
+
+	if (bInitFailed)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Module initialisation failed", __FUNCTION__));
+		return -EINVAL;
+	}
+
+	return PVRSRVOpen(dev, file);
+}
+
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE) || defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+DRI_DRM_STATIC int
+PVRSRVDrmRelease(struct drm_device *dev, struct drm_file *file)
+#else
+DRI_DRM_STATIC void
+PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+#endif
+{
+	PVRSRVRelease(file->driver_priv);
+
+	file->driver_priv = NULL;
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+	return 0;
+#endif
+}
+#else
+DRI_DRM_STATIC int
+PVRSRVDrmRelease(struct inode *inode, struct file *filp)
+{
+	struct drm_file *file_priv = filp->private_data;
+	void *psDriverPriv = file_priv->driver_priv;
+	int ret;
+
+	ret = drm_release(inode, filp);
+
+	if (ret != 0)
+	{
+		/*
+		 * An error means drm_release didn't call drm_lastclose,
+		 * but it will have freed file_priv.
+		 */
+		PVR_DPF((PVR_DBG_ERROR, "%s : drm_release failed: %d",
+			__FUNCTION__, ret));
+	}
+
+	PVRSRVRelease(psDriverPriv);
+
+	return 0;
+}
+#endif
+
+DRI_DRM_STATIC int
+PVRDRMIsMaster(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+	return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+int
+PVRDRM_Dummy_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+	return 0;
+}
+#endif
+
+DRI_DRM_STATIC int
+PVRDRMUnprivCmd(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+	int ret = 0;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	if (arg == NULL)
+	{
+		ret = -EFAULT;
+	}
+	else
+	{
+		drm_pvr_unpriv_cmd *psArgs = (drm_pvr_unpriv_cmd *)arg;
+
+		switch (psArgs->cmd)
+		{
+			case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+				psArgs->res = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+				break;
+
+			default:
+				ret = -EFAULT;
+		}
+
+	}
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	return ret;
+}
+
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+static int
+PVRDRM_Display_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+	int res;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	res = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(dev, arg, pFile);
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	return res;
+}
+#endif
+
+#if defined(SUPPORT_DRM_MODESET)
+static int
+PVRSRVPciProbe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	PVR_TRACE(("PVRSRVPciProbe"));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36))
+	return drm_get_pci_dev(dev, id, &sPVRDrmDriver);
+#else
+	return drm_get_dev(dev, id, &sPVRDrmDriver);
+#endif
+}
+
+static void
+PVRSRVPciRemove(struct pci_dev *dev)
+{
+	struct drm_device *psDrmDev;
+
+	PVR_TRACE(("PVRSRVPciRemove"));
+
+	psDrmDev = pci_get_drvdata(dev);
+	drm_put_dev(psDrmDev);
+}
+#endif
+
+/*
+ * For Linux 2.6.33 and above, the DRM ioctl entry point is of the unlocked
+ * variety.  The big kernel lock is still taken for ioctls, unless
+ * the DRM_UNLOCKED flag is set.  If you revise one of the driver specific
+ * ioctls, or add a new one, consider whether the gPVRSRVLock mutex needs
+ * to be taken.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+#define	PVR_DRM_FOPS_IOCTL	.unlocked_ioctl
+#define	PVR_DRM_UNLOCKED	DRM_UNLOCKED
+#else
+#define	PVR_DRM_FOPS_IOCTL	.ioctl
+#define	PVR_DRM_UNLOCKED	0
+#endif
+
+#if !defined(DRM_IOCTL_DEF_DRV)
+#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) DRM_IOCTL_DEF(DRM_##ioctl, _func, _flags)
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+	DRM_IOCTL_DEF_DRV(PVR_SRVKM, PVRSRV_BridgeDispatchKM, PVR_DRM_RENDER_ALLOW | PVR_DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(PVR_IS_MASTER, PVRDRMIsMaster, PVR_DRM_RENDER_ALLOW | DRM_MASTER | PVR_DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(PVR_UNPRIV, PVRDRMUnprivCmd, PVR_DRM_RENDER_ALLOW | PVR_DRM_UNLOCKED),
+#if defined(PDUMP)
+	DRM_IOCTL_DEF_DRV(PVR_DBGDRV, dbgdrv_ioctl, PVR_DRM_RENDER_ALLOW | PVR_DRM_UNLOCKED),
+#endif
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+	DRM_IOCTL_DEF_DRV(PVR_DISP, PVRDRM_Display_ioctl, DRM_MASTER | PVR_DRM_UNLOCKED)
+#endif
+};
+
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
+static int pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+#endif
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \
+	!defined(SUPPORT_DRI_DRM_PLUGIN)
+static int PVRSRVDrmProbe(struct platform_device *pDevice);
+static int PVRSRVDrmRemove(struct platform_device *pDevice);
+#endif	/* defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+static PVRSRV_DRM_PLUGIN sPVRDrmPlugin =
+{
+	.name = PVR_DRM_NAME,
+
+	.open = PVRSRVDrmOpen,
+	.load = PVRSRVDrmLoad,
+	.unload = PVRSRVDrmUnload,
+
+	.release = PVRSRVDrmRelease,
+
+	.mmap = PVRMMap,
+
+	.ioctls = sPVRDrmIoctls,
+	.num_ioctls = DRM_ARRAY_SIZE(sPVRDrmIoctls),
+	.ioctl_start = 0
+};
+#else	/* defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+#if defined(CONFIG_COMPAT)
+static long pvr_compat_ioctl(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+
+	if (nr < DRM_COMMAND_BASE)
+	{
+		return drm_compat_ioctl(file, cmd, arg);
+	}
+
+	return drm_ioctl(file, cmd, arg);
+}
+#endif /* defined(CONFIG_COMPAT) */
+
+static const struct file_operations sPVRFileOps = 
+{
+	.owner = THIS_MODULE,
+	.open = drm_open,
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+	.release = drm_release,
+#else
+	.release = PVRSRVDrmRelease,
+#endif
+	PVR_DRM_FOPS_IOCTL = drm_ioctl,
+#if defined(CONFIG_COMPAT)
+	.compat_ioctl  = pvr_compat_ioctl,
+#endif
+	.mmap = PVRMMap,
+	.poll = drm_poll,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0))
+	.fasync = drm_fasync,
+#endif
+};
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
+
+static struct drm_driver sPVRDrmDriver = 
+{
+	.driver_features = PVR_DRM_DRIVER_RENDER
+#if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV)
+		| DRIVER_USE_PLATFORM_DEVICE
+#endif
+		,
+	.dev_priv_size = 0,
+	.load = PVRSRVDrmLoad,
+	.unload = PVRSRVDrmUnload,
+	.open = PVRSRVDrmOpen,
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+	.postclose = PVRSRVDrmPostClose,
+#endif
+#if !defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRM_MODESET)
+	.suspend = PVRSRVDriverSuspend,
+	.resume = PVRSRVDriverResume,
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37))
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+#endif
+	.ioctls = sPVRDrmIoctls,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
+	.fops = &sPVRFileOps,
+#else
+	.fops = 
+	{
+		.owner = THIS_MODULE,
+		.open = drm_open,
+#if defined(PVR_DRI_DRM_USE_POST_CLOSE)
+		.release = drm_release,
+#else
+		.release = PVRSRVDrmRelease,
+#endif
+		PVR_DRM_FOPS_IOCTL = drm_ioctl,
+		.mmap = PVRMMap,
+		.poll = drm_poll,
+		.fasync = drm_fasync,
+	},
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+#if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV)
+	.platform_driver =
+	{
+		.id_table = asPlatIdList,
+		.driver =
+		{
+			.name = PVR_DRM_NAME,
+		},
+		.probe = PVRSRVDrmProbe,
+		.remove = PVRSRVDrmRemove,
+		.suspend = PVRSRVDriverSuspend,
+		.resume = PVRSRVDriverResume,
+		.shutdown = PVRSRVDriverShutdown,
+	},
+#else
+	.pci_driver = 
+	{
+		.name = PVR_DRM_NAME,
+		.id_table = asPciIdList,
+#if defined(SUPPORT_DRM_MODESET)
+		.probe = PVRSRVPciProbe,
+		.remove = PVRSRVPciRemove,
+		.suspend = PVRSRVDriverSuspend,
+		.resume = PVRSRVDriverResume,
+#endif
+	},
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0))
+#if defined(LDM_PLATFORM)
+	.set_busid = drm_platform_set_busid,
+#else
+#if defined(LDM_PCI)
+	.set_busid = drm_pci_set_busid,
+#else
+	#error "LDM_PLATFORM or LDM_PCI must be set"
+#endif
+#endif
+#endif
+	.name = "pvr",
+	.desc = PVR_DRM_DESC,
+	.date = PVR_DRM_DATE,
+	.major = PVRVERSION_MAJ,
+	.minor = PVRVERSION_MIN,
+	.patchlevel = PVRVERSION_BUILD,
+};
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) && !defined(PVR_DRI_DRM_PLATFORM_DEV)
+static struct pci_driver sPVRPCIDriver =
+{
+		.name = PVR_DRM_NAME,
+		.id_table = asPciIdList,
+#if defined(SUPPORT_DRM_MODESET)
+		.probe = PVRSRVPciProbe,
+		.remove = PVRSRVPciRemove,
+		.suspend = PVRSRVDriverSuspend,
+		.resume = PVRSRVDriverResume,
+#endif
+};
+#endif
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+#if !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+static struct platform_device_info sPVRPlatDeviceInfo = {
+	.name			= PVR_DRM_NAME,
+	.id			= -1,
+	.dma_mask = DMA_BIT_MASK(32)
+};
+#endif
+
+static struct platform_driver sPVRPlatDriver =
+{
+#if !defined(PVR_USE_DEVICE_TREE)
+	.id_table = asPlatIdList,
+#endif
+	.driver =
+	{
+		.name = PVR_DRM_NAME,
+#if defined(PVR_USE_DEVICE_TREE)
+		.of_match_table = asPlatIdList,
+#endif
+	},
+	.probe = PVRSRVDrmProbe,
+	.remove = PVRSRVDrmRemove,
+	.suspend = PVRSRVDriverSuspend,
+	.resume = PVRSRVDriverResume,
+	.shutdown = PVRSRVDriverShutdown,
+};
+#endif
+
+#endif	/* defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \
+	!defined(SUPPORT_DRI_DRM_PLUGIN)
+static int
+PVRSRVDrmProbe(struct platform_device *pDevice)
+{
+	PVR_TRACE(("PVRSRVDrmProbe"));
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+	gpsPVRLDMDev = pDevice;
+
+	return drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+	return drm_get_platform_dev(pDevice, &sPVRDrmDriver);
+#endif
+}
+
+static int
+PVRSRVDrmRemove(struct platform_device *pDevice)
+{
+	PVR_TRACE(("PVRSRVDrmRemove"));
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+	drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+	drm_put_dev(gpsPVRDRMDev);
+#endif
+	return 0;
+}
+#endif
+
+static int __init PVRSRVDrmInit(void)
+{
+	int iRes;
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
+	sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+#endif
+
+#if defined(SUPPORT_DRM_MODESET)
+	sPVRDrmDriver.driver_features |= DRIVER_MODESET;
+#endif
+
+	/* Must come before attempting to print anything via Services */
+	PVRDPFInit();
+
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+	iRes = platform_driver_register(&sPVRPlatDriver);
+#if !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+	if (iRes == 0)
+	{
+		psPlatDev = platform_device_register_full(&sPVRPlatDeviceInfo);
+		if (IS_ERR(psPlatDev))
+		{
+			iRes = PTR_ERR(psPlatDev);
+			psPlatDev = NULL;
+			platform_driver_unregister(&sPVRPlatDriver);
+		}
+	}
+#endif
+#else	/* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+	iRes = SysDRMRegisterPlugin(&sPVRDrmPlugin);
+#else	/* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#if defined(PVR_DRI_DRM_NOT_PCI)
+	iRes = drm_pvr_dev_add();
+	if (iRes != 0)
+	{
+		return iRes;
+	}
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+	iRes = drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+	iRes = drm_pci_init(&sPVRDrmDriver, &sPVRPCIDriver);
+#endif
+#else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+	iRes = drm_init(&sPVRDrmDriver);
+#endif	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+	if (iRes != 0)
+	{
+		drm_pvr_dev_remove();
+	}
+#endif
+#endif	/* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#endif	/* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+	return iRes;
+}
+	
+static void __exit PVRSRVDrmExit(void)
+{
+#if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV)
+#if !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
+	platform_device_unregister(psPlatDev);
+#endif
+	platform_driver_unregister(&sPVRPlatDriver);
+#else	/* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+	SysDRMUnregisterPlugin(&sPVRDrmPlugin);
+#else	/* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+	drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev);
+#else
+	drm_pci_exit(&sPVRDrmDriver, &sPVRPCIDriver);
+#endif
+#else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+	drm_exit(&sPVRDrmDriver);
+#endif	/* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+	drm_pvr_dev_remove();
+#endif
+#endif	/* defined(SUPPORT_DRI_DRM_PLUGIN) */
+#endif	/* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */
+}
+
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver.  Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif	/* !defined(SUPPORT_DRI_DRM_EXT) */
+#endif	/* defined(SUPPORT_DRI_DRM) */
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.h
new file mode 100644
index 0000000..1d6e274
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.h
@@ -0,0 +1,185 @@
+/*************************************************************************/ /*!
+@Title          PowerVR drm driver
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    drm module 
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#if defined (PDUMP)
+#include "linuxsrv.h"
+#endif
+
+#include "pvr_drm_shared.h"
+
+#if defined(SUPPORT_DRI_DRM)
+
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+#include "3rdparty_dc_drm_shared.h"
+#endif
+
+#define	PVR_DRM_MAKENAME_HELPER(x, y) x ## y
+#define	PVR_DRM_MAKENAME(x, y) PVR_DRM_MAKENAME_HELPER(x, y)
+
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+#define	LDM_DEV	struct platform_device
+#endif
+
+int PVRCore_Init(void);
+void PVRCore_Cleanup(void);
+int PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+void PVRSRVRelease(void *pvPrivData);
+
+#if !defined(SUPPORT_DRI_DRM_PLUGIN)
+#if defined(PVR_DRI_DRM_PLATFORM_DEV)
+void PVRSRVDriverShutdown(LDM_DEV *pDevice);
+int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state);
+int PVRSRVDriverResume(LDM_DEV *pDevice);
+#else
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverSuspend(struct pci_dev *pDevice, pm_message_t state);
+int PVRSRVDriverResume(struct pci_dev *pDevice);
+#else
+int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+int PVRSRVDriverResume(struct drm_device *pDevice);
+#endif /* defined(SUPPORT_DRM_MODESET) */
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+#endif /* !defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile);
+int PVRSRV_BridgeCompatDispatchKM(struct drm_device *dev, void *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define	DRI_DRM_STATIC
+/*Exported functions to common drm layer*/
+int PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
+int PVRSRVDrmUnload(struct drm_device *dev);
+int PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+DRI_DRM_STATIC int PVRSRVDrmRelease(struct inode *inode, struct file *filp);
+#else
+void PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+#endif
+int PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define	DRI_DRM_STATIC	static
+#endif	/* defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(DISPLAY_CONTROLLER)
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(struct drm_device *);
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(struct drm_device *);
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device *dev, void *arg, struct drm_file *pFile);
+#endif
+#endif
+
+#if defined(PDUMP)
+int dbgdrv_init(void);
+void dbgdrv_cleanup(void);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+/*
+ * We need the command number names to begin with "DRM_" for newer versions
+ * of the macro used to fill out the DRM ioctl table.  Similarly, the
+ * ioctl number names must begin with "DRM_IOCTL_". The suffixes for the
+ * two sets of strings must match (e.g. end with "PVR_SRVKM" in both
+ * cases).
+ */
+
+#define	DRM_PVR_SRVKM		PVR_DRM_SRVKM_CMD
+#define	DRM_PVR_IS_MASTER	PVR_DRM_IS_MASTER_CMD
+#define	DRM_PVR_UNPRIV		PVR_DRM_UNPRIV_CMD
+#define	DRM_PVR_DBGDRV		PVR_DRM_DBGDRV_CMD
+#define	DRM_PVR_DISP		PVR_DRM_DISP_CMD
+
+/*
+ * Some versions of the kernel will dereference a NULL pointer if data is
+ * is passed to an ioctl that doesn't expect any, so avoid using the _IO
+ * macro, and use _IOW instead, specifying a dummy argument.
+*/
+typedef struct {
+	char dummy[4];
+} drm_pvr_dummy_arg;
+
+/* IOCTL numbers */
+#define	DRM_IOCTL_PVR_SRVKM	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_SRVKM, PVRSRV_BRIDGE_PACKAGE)
+#define	DRM_IOCTL_PVR_IS_MASTER DRM_IOW(DRM_COMMAND_BASE + DRM_PVR_IS_MASTER, drm_pvr_dummy_arg)
+#define	DRM_IOCTL_PVR_UNPRIV	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_UNPRIV, drm_pvr_unpriv_cmd)
+
+#if defined(PDUMP)
+#define	DRM_IOCTL_PVR_DBGDRV	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_DBGDRV, IOCTL_PACKAGE)
+#endif
+
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+#define	DRM_IOCTL_PVR_DISP	DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_DISP, drm_pvr_display_cmd)
+#endif
+#endif	/* !defined(SUPPORT_DRI_DRM_EXT) */
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+typedef	struct {
+	char *name;
+
+	int (*load)(struct drm_device *dev, unsigned long flags);
+	int (*unload)(struct drm_device *dev);
+
+	int (*open)(struct drm_device *dev, struct drm_file *file);
+	int (*release)(struct drm_device *dev, struct drm_file *file);
+
+	int (*mmap)(struct file* pFile, struct vm_area_struct* ps_vma);
+
+	struct drm_ioctl_desc *ioctls;
+	int num_ioctls;
+	int ioctl_start;
+} PVRSRV_DRM_PLUGIN;
+
+int SysDRMRegisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin);
+void SysDRMUnregisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin);
+#endif	/* defined(SUPPORT_DRI_DRM_PLUGIN) */
+
+#endif	/* defined(SUPPORT_DRI_DRM) */
+
+#endif /* defined(__PVR_DRM_H__) */
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_fence.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_fence.c
new file mode 100644
index 0000000..64d2b6a
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_fence.c
@@ -0,0 +1,1688 @@
+/*************************************************************************/ /*!
+@File
+@Title          PowerVR Linux fence interface
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#include "pvr_sync_common.h"
+#include "pvr_fence.h"
+#include "pvr_counting_timeline.h"
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/anon_inodes.h>
+#include <linux/seq_file.h>
+#include <linux/sync_file.h>
+
+#include "services_headers.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+#include "mutex.h"
+#include "lock.h"
+
+//#define DEBUG_PRINT
+
+#if defined(DEBUG_PRINT)
+#define DPF(fmt, ...) PVR_DPF((PVR_DBG_BUFFERED, fmt, __VA_ARGS__))
+#else
+#define DPF(fmt, ...) do {} while(0)
+#endif
+
+struct sw_sync_create_fence_data {
+	__u32 value;
+	char name[32];
+	__s32 fence;
+};
+#define SW_SYNC_IOC_MAGIC 'W'
+#define SW_SYNC_IOC_CREATE_FENCE \
+	(_IOWR(SW_SYNC_IOC_MAGIC, 0, struct sw_sync_create_fence_data))
+#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+/* Gobal WQ for scheduling work */
+static struct workqueue_struct *gpsWorkQueue;
+
+/* Linux work struct for workqueue. */
+static struct work_struct gsWork;
+
+static const struct file_operations pvr_sync_fops;
+
+/* The "defer-free" object list. Driver global. */
+static LIST_HEAD(gSyncInfoFreeList);
+static DEFINE_SPINLOCK(gSyncInfoFreeListLock);
+
+/* List of timelines, used by MISR callback to find signaled fences
+ * and also to kick the hardware if signalling may allow progress to be
+ * made.
+ */
+static LIST_HEAD(gFenceCtxList);
+static DEFINE_MUTEX(gFenceCtxListLock);
+
+/* Forward declare due to cyclic dependency on gsSyncFenceAllocFOps */
+struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd);
+
+/* Global data for the sync driver */
+static struct {
+	/* Process that initialized the sync driver. House-keep this so
+	 * the correct per-proc data is used during shutdown. This PID is
+	 * conventionally whatever `pvrsrvctl' was when it was alive.
+	 */
+	IMG_UINT32	ui32Pid;
+
+	/* Device cookie for services allocation functions. The device would
+	 * ordinarily be SGX, and the first/only device in the system.
+	 */
+	IMG_HANDLE	hDevCookie;
+
+	/* Device memory context that all SYNC_INFOs allocated by this driver
+	 * will be created in. Because SYNC_INFOs are placed in a shared heap,
+	 * it does not matter from which process the create ioctl originates.
+	 */
+	IMG_HANDLE	hDevMemContext;
+	struct PVR_FENCE_CONTEXT *psForeignFenceCtx;
+}
+gsSyncServicesConnection;
+
+
+/* NOTE: Must only be called with services bridge mutex held */
+static void PVRSyncSWTakeOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+	psKernelSyncInfo->psSyncData->ui32WriteOpsPending = 1;
+}
+
+static void PVRSyncSWCompleteOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+	psKernelSyncInfo->psSyncData->ui32WriteOpsComplete = 1;
+}
+
+#define PVR_DUMPDEBUG_LOG(fmt, ...) \
+	do {                                                             \
+		PVR_DPF((PVR_DBG_ERROR, fmt "\n", ## __VA_ARGS__));      \
+	} while (0)
+
+static IMG_BOOL PVRSyncIsSyncInfoInUse(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo)
+{
+
+	return !(psSyncInfo->psSyncData->ui32WriteOpsPending ==
+			 psSyncInfo->psSyncData->ui32WriteOpsComplete &&
+			 psSyncInfo->psSyncData->ui32ReadOpsPending ==
+			 psSyncInfo->psSyncData->ui32ReadOpsComplete &&
+			 psSyncInfo->psSyncData->ui32ReadOps2Pending ==
+			 psSyncInfo->psSyncData->ui32ReadOps2Complete);
+}
+
+static inline bool
+pvr_fence_sync_value_met(struct PVR_FENCE *psPVRFence)
+{
+	return !PVRSyncIsSyncInfoInUse(psPVRFence->psSyncData->psSyncInfo->psBase);
+}
+
+static void PVRSyncReleaseSyncInfo(struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gSyncInfoFreeListLock, flags);
+	list_add_tail(&psSyncInfo->sHead, &gSyncInfoFreeList);
+	spin_unlock_irqrestore(&gSyncInfoFreeListLock, flags);
+
+	queue_work(gpsWorkQueue, &gsWork);
+}
+
+static void PVRSyncFreeSyncData(struct PVR_SYNC_DATA *psSyncData)
+{
+	PVRSyncReleaseSyncInfo(psSyncData->psSyncInfo);
+	psSyncData->psSyncInfo = NULL;
+	kfree(psSyncData);
+}
+
+static void
+pvr_fence_context_fences_dump(struct PVR_FENCE_CONTEXT *psFenceCtx)
+{
+	struct PVR_FENCE *psPVRFence;
+	unsigned long flags;
+
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_for_each_entry(psPVRFence, &psFenceCtx->sFenceList, sFenceHead)
+	{
+		PVR_DUMPDEBUG_LOG(
+			"f %llu: WOCVA=0x%.8X WriteOps P %d C %d ReadOps P %d C %d ReadOps2 P %d C %d, %s %s",
+			(u64) psPVRFence->psFenceCtx->ui64FenceCtx,
+			psPVRFence->psSyncData->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+			psPVRFence->psSyncData->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+			psPVRFence->psSyncData->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete,
+			psPVRFence->psSyncData->psSyncInfo->psBase->psSyncData->ui32ReadOpsPending,
+			psPVRFence->psSyncData->psSyncInfo->psBase->psSyncData->ui32ReadOpsComplete,
+			psPVRFence->psSyncData->psSyncInfo->psBase->psSyncData->ui32ReadOps2Pending,
+			psPVRFence->psSyncData->psSyncInfo->psBase->psSyncData->ui32ReadOps2Complete,
+			psPVRFence->pName,
+			(&psPVRFence->sBase != psPVRFence->psFence) ? "(foreign)" : "");
+	}
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+}
+
+static inline
+IMG_UINT32 pvr_fence_context_seqno_next(struct PVR_FENCE_CONTEXT *psFenceCtx)
+{
+	return atomic_inc_return(&psFenceCtx->sSeqno) - 1;
+}
+
+static inline void
+pvr_fence_context_free_deferred(struct PVR_FENCE_CONTEXT *psFenceCtx)
+{
+	struct PVR_FENCE *psPVRFence, *psPVRFenceTmp;
+	LIST_HEAD(deferred_free_list);
+	unsigned long flags;
+#if defined(DEBUG_PRINT)
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+#endif
+
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_for_each_entry_safe(psPVRFence, psPVRFenceTmp, &psFenceCtx->sDeferredFreeList, sFenceHead)
+	{
+		list_move(&psPVRFence->sFenceHead, &deferred_free_list);
+	}
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+
+	list_for_each_entry_safe(psPVRFence, psPVRFenceTmp, &deferred_free_list, sFenceHead)
+	{
+#if defined(DEBUG_PRINT)
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = psPVRFence->psSyncData->psSyncInfo->psBase;
+#endif
+		list_del(&psPVRFence->sFenceHead);
+		DPF("R( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X "
+			"WOP/C=0x%x/0x%x ROP/C=0x%x/0x%x RO2P/C=0x%x/0x%x "
+			"S=0x%x, Name=%s",
+			psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr,
+			psSyncInfo->psSyncData->ui32WriteOpsPending,
+			psSyncInfo->psSyncData->ui32WriteOpsComplete,
+			psSyncInfo->psSyncData->ui32ReadOpsPending,
+			psSyncInfo->psSyncData->ui32ReadOpsComplete,
+			psSyncInfo->psSyncData->ui32ReadOps2Pending,
+			psSyncInfo->psSyncData->ui32ReadOps2Complete,
+			psPVRFence->psSyncData->ui32WOPSnapshot,
+			psPVRFence->pName);
+		PVRSyncFreeSyncData(psPVRFence->psSyncData);
+		dma_fence_free(&psPVRFence->sBase);
+	}
+}
+
+static void
+pvr_fence_context_destroy_work(struct work_struct *psData)
+{
+	struct PVR_FENCE_CONTEXT *psFenceCtx =
+		container_of(psData, struct PVR_FENCE_CONTEXT, sDestroyWork);
+
+	pvr_fence_context_free_deferred(psFenceCtx);
+
+	if (WARN_ON(!list_empty_careful(&psFenceCtx->sFenceList)))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "List is not empty in pvr_fence_context_destroy_kref"));
+		pvr_fence_context_fences_dump(psFenceCtx);
+	}
+
+	destroy_workqueue(psFenceCtx->psFenceWq);
+
+	kfree(psFenceCtx);
+}
+
+static void
+pvr_fence_context_destroy_kref(struct kref *pKref)
+{
+	struct PVR_FENCE_CONTEXT *psFenceCtx =
+		container_of(pKref, struct PVR_FENCE_CONTEXT, sRef);
+
+	schedule_work(&psFenceCtx->sDestroyWork);
+}
+
+/**
+ * pvr_fence_context_destroy - destroys a context
+ * @fctx: PVR fence context to destroy
+ *
+ * Destroys a PVR fence context with the expectation that all fences have been
+ * destroyed.
+ */
+void
+pvr_fence_context_destroy(struct PVR_FENCE_CONTEXT *psFenceCtx)
+{
+	mutex_lock(&gFenceCtxListLock);
+	list_del(&psFenceCtx->sFenceCtxList);
+	mutex_unlock(&gFenceCtxListLock);
+
+	kref_put(&psFenceCtx->sRef, pvr_fence_context_destroy_kref);
+}
+
+static void
+pvr_fence_context_signal_fences(struct work_struct *psData)
+{
+	struct PVR_FENCE_CONTEXT *psFenceCtx =
+		container_of(psData, struct PVR_FENCE_CONTEXT, sSignalWork);
+	struct PVR_FENCE *psPVRFence, *psPVRTmp;
+	unsigned long flags;
+	LIST_HEAD(signal_list);
+
+	/*
+	 * We can't call fence_signal while holding the lock as we can end up
+	 * in a situation whereby pvr_fence_foreign_signal_sync, which also
+	 * takes the list lock, ends up being called as a result of the
+	 * fence_signal below, i.e. fence_signal(fence) -> fence->callback()
+	 *  -> fence_signal(foreign_fence) -> foreign_fence->callback() where
+	 * the foreign_fence callback is pvr_fence_foreign_signal_sync.
+	 *
+	 * So extract the items we intend to signal and add them to their own
+	 * queue.
+	 */
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_for_each_entry_safe(psPVRFence, psPVRTmp, &psFenceCtx->sSignalList, sSignalHead)
+	{
+		if (pvr_fence_sync_value_met(psPVRFence))
+		{
+			list_move(&psPVRFence->sSignalHead, &signal_list);
+		}
+	}
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+
+	list_for_each_entry_safe(psPVRFence, psPVRTmp, &signal_list, sSignalHead)
+	{
+
+		PVR_FENCE_TRACE(&psPVRFence->sBase, "signalled fence (%s) %p\n", psPVRFence->pName, psPVRFence);
+		list_del(&psPVRFence->sSignalHead);
+		dma_fence_signal(psPVRFence->psFence);
+		dma_fence_put(psPVRFence->psFence);
+	}
+
+	/*
+	 * Take this opportunity to free up any fence objects we
+	 * have deferred freeing.
+	 */
+	pvr_fence_context_free_deferred(psFenceCtx);
+
+	/* Put back ref taken duing queing of fence context work */
+	kref_put(&psFenceCtx->sRef, pvr_fence_context_destroy_kref);
+}
+
+IMG_INTERNAL
+void PVRSyncUpdateAllSyncs(void)
+{
+	IMG_BOOL bNeedToProcessQueues = IMG_FALSE;
+	struct list_head *psEntry;
+
+	/* Check to see if any syncs have signalled. If they have, it may unblock
+	 * the GPU. Decide what is needed and optionally schedule queue
+	 * processing.
+	 */
+	mutex_lock(&gFenceCtxListLock);
+	list_for_each(psEntry, &gFenceCtxList)
+	{
+		struct PVR_FENCE_CONTEXT *psFenceCtx = container_of(psEntry, struct PVR_FENCE_CONTEXT, sFenceCtxList);
+
+		if(psFenceCtx->bSyncHasSignaled)
+		{
+			psFenceCtx->bSyncHasSignaled = IMG_FALSE;
+			bNeedToProcessQueues = IMG_TRUE;
+		}
+		/*
+		 * We need to take a reference on fence context as this
+		 * function and fence context destruction call can come
+		 * in any order. And release it in after serving work.
+		*/
+		kref_get(&psFenceCtx->sRef);
+		queue_work(psFenceCtx->psFenceWq, &psFenceCtx->sSignalWork);
+	}
+	mutex_unlock(&gFenceCtxListLock);
+
+	if(bNeedToProcessQueues)
+	{
+		queue_work(gpsWorkQueue, &gsWork);
+	}
+}
+
+/**
+ * pvr_fence_context_create - creates a PVR fence context
+ * @name: context name (used for debugging)
+ *
+ * Creates a PVR fence context that can be used to create PVR fences or to
+ * create PVR fences from an existing fence.
+ *
+ * pvr_fence_context_destroy should be called to clean up the fence context.
+ *
+ * Returns NULL if a context cannot be created.
+ */
+struct PVR_FENCE_CONTEXT *
+pvr_fence_context_create(const char *pName)
+{
+	struct PVR_FENCE_CONTEXT *psFenceCtx;
+
+	psFenceCtx = kzalloc(sizeof(*psFenceCtx), GFP_KERNEL);
+	if (!psFenceCtx)
+		return NULL;
+
+	spin_lock_init(&psFenceCtx->sLock);
+	atomic_set(&psFenceCtx->sSeqno, 0);
+	INIT_WORK(&psFenceCtx->sSignalWork, pvr_fence_context_signal_fences);
+	INIT_WORK(&psFenceCtx->sDestroyWork, pvr_fence_context_destroy_work);
+	spin_lock_init(&psFenceCtx->sListLock);
+	INIT_LIST_HEAD(&psFenceCtx->sSignalList);
+	INIT_LIST_HEAD(&psFenceCtx->sFenceList);
+	INIT_LIST_HEAD(&psFenceCtx->sDeferredFreeList);
+
+	psFenceCtx->ui64FenceCtx = dma_fence_context_alloc(1);
+	psFenceCtx->pName = pName;
+	psFenceCtx->bSyncHasSignaled = IMG_FALSE;
+
+	psFenceCtx->psFenceWq = create_freezable_workqueue("pvr_fence_sync_workqueue");
+	if (!psFenceCtx->psFenceWq)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"%s: failed to create fence workqueue\n", __func__));
+		goto err_destroy_workqueue;
+	}
+
+	kref_init(&psFenceCtx->sRef);
+
+	mutex_lock(&gFenceCtxListLock);
+	list_add_tail(&psFenceCtx->sFenceCtxList, &gFenceCtxList);
+	mutex_unlock(&gFenceCtxListLock);
+
+	PVR_FENCE_CTX_TRACE(psFenceCtx, "created fence context (%s)\n", pName);
+
+	return psFenceCtx;
+
+err_destroy_workqueue:
+	destroy_workqueue(psFenceCtx->psFenceWq);
+	kfree(psFenceCtx);
+	return NULL;
+}
+
+static const char *
+pvr_fence_get_driver_name(struct dma_fence *psFence)
+{
+	return PVR_LDM_DRIVER_REGISTRATION_NAME;
+}
+
+static const char *
+pvr_fence_get_timeline_name(struct dma_fence *psFence)
+{
+	struct PVR_FENCE *psPVRFence = to_pvr_fence(psFence);
+
+	return psPVRFence->psFenceCtx->pName;
+}
+
+static bool
+pvr_fence_enable_signaling(struct dma_fence *psFence)
+{
+	struct PVR_FENCE *psPVRFence = to_pvr_fence(psFence);
+	struct PVR_FENCE_CONTEXT *psFenceCtx = psPVRFence->psFenceCtx;
+	unsigned long flags;
+
+	WARN_ON_SMP(!spin_is_locked(&psFenceCtx->sLock));
+
+	if (pvr_fence_sync_value_met(psPVRFence))
+	{
+		return false;
+	}
+
+	dma_fence_get(&psPVRFence->sBase);
+
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_add_tail(&psPVRFence->sSignalHead, &psFenceCtx->sSignalList);
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+
+	PVR_FENCE_TRACE(&psPVRFence->sBase, "signalling enabled (%p)\n", psPVRFence);
+
+	return true;
+}
+
+static bool
+pvr_fence_is_signaled(struct dma_fence *psFence)
+{
+	struct PVR_FENCE *psPVRFence = to_pvr_fence(psFence);
+
+	if(pvr_fence_sync_value_met(psPVRFence))
+	{
+		psPVRFence->psFenceCtx->bSyncHasSignaled = IMG_TRUE;
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+static void
+pvr_fence_release(struct dma_fence *psFence)
+{
+	struct PVR_FENCE *psPVRFence = to_pvr_fence(psFence);
+	struct PVR_FENCE_CONTEXT *psFenceCtx = psPVRFence->psFenceCtx;
+	unsigned long flags;
+
+	PVR_FENCE_TRACE(&psPVRFence->sBase, "released fence (%s) %p\n", psPVRFence->pName, psPVRFence);
+
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_move(&psPVRFence->sFenceHead, &psFenceCtx->sDeferredFreeList);
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+
+	kref_put(&psFenceCtx->sRef, pvr_fence_context_destroy_kref);
+}
+
+const struct dma_fence_ops pvr_fence_ops = {
+	.get_driver_name = pvr_fence_get_driver_name,
+	.get_timeline_name = pvr_fence_get_timeline_name,
+	.enable_signaling = pvr_fence_enable_signaling,
+	.signaled = pvr_fence_is_signaled,
+	.wait = dma_fence_default_wait,
+	.release = pvr_fence_release,
+};
+
+/**
+ * pvr_fence_create - creates a PVR fence
+ * @fctx: PVR fence context on which the PVR fence should be created
+ * @name: PVR fence name (used for debugging)
+ *
+ * Creates a PVR fence.
+ *
+ * Once the fence is finished with pvr_fence_destroy should be called.
+ *
+ * Returns NULL if a PVR fence cannot be created.
+ */
+struct PVR_FENCE *
+pvr_fence_create(struct PVR_FENCE_CONTEXT *psFenceCtx, const char *name, struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo)
+{
+	struct PVR_FENCE *psPVRFence;
+	unsigned int seqno;
+	unsigned long flags;
+
+	psPVRFence = kzalloc(sizeof(*psPVRFence), GFP_KERNEL);
+	if (!psPVRFence)
+		return NULL;
+
+	psPVRFence->psSyncData = kmalloc(sizeof(struct PVR_SYNC_DATA), GFP_KERNEL);
+	if(!psPVRFence->psSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_SYNC_DATA", __func__));
+		goto err_free_fence;
+	}
+	psPVRFence->psSyncData->psSyncInfo = psSyncInfo;
+
+	INIT_LIST_HEAD(&psPVRFence->sFenceHead);
+	INIT_LIST_HEAD(&psPVRFence->sSignalHead);
+	psPVRFence->psFenceCtx = psFenceCtx;
+	psPVRFence->pName = name;
+	psPVRFence->psFence = &psPVRFence->sBase;
+
+	seqno = pvr_fence_context_seqno_next(psFenceCtx);
+	dma_fence_init(&psPVRFence->sBase, &pvr_fence_ops, &psFenceCtx->sLock,
+		       psFenceCtx->ui64FenceCtx, seqno);
+
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_add_tail(&psPVRFence->sFenceHead, &psFenceCtx->sFenceList);
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+
+	kref_get(&psFenceCtx->sRef);
+
+	PVR_FENCE_TRACE(&psPVRFence->sBase, "created fence (%s) %p\n", name, psPVRFence);
+
+	return psPVRFence;
+
+err_free_fence:
+	kfree(psPVRFence);
+	return NULL;
+}
+
+static const char *
+pvr_fence_foreign_get_driver_name(struct dma_fence *psFence)
+{
+	return "unknown";
+}
+
+static const char *
+pvr_fence_foreign_get_timeline_name(struct dma_fence *psFence)
+{
+	return "unknown";
+}
+
+static bool
+pvr_fence_foreign_enable_signaling(struct dma_fence *psFence)
+{
+	WARN_ON("cannot enable signalling on foreign fence");
+	return false;
+}
+
+static signed long
+pvr_fence_foreign_wait(struct dma_fence *psFence, bool intr, signed long timeout)
+{
+	WARN_ON("cannot wait on foreign fence");
+	return 0;
+}
+
+static void
+pvr_fence_foreign_release(struct dma_fence *psFence)
+{
+	struct PVR_FENCE *psPVRFence = to_pvr_fence(psFence);
+	struct PVR_FENCE_CONTEXT *psFenceCtx = psPVRFence->psFenceCtx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_move(&psPVRFence->sFenceHead, &psFenceCtx->sDeferredFreeList);
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+
+	kref_put(&psFenceCtx->sRef, pvr_fence_context_destroy_kref);
+}
+
+const struct dma_fence_ops pvr_fence_foreign_ops = {
+	.get_driver_name = pvr_fence_foreign_get_driver_name,
+	.get_timeline_name = pvr_fence_foreign_get_timeline_name,
+	.enable_signaling = pvr_fence_foreign_enable_signaling,
+	.wait = pvr_fence_foreign_wait,
+	.release = pvr_fence_foreign_release,
+};
+
+static void
+pvr_fence_foreign_signal_sync(struct dma_fence *psFence, struct dma_fence_cb *psCb)
+{
+	struct PVR_FENCE *psPVRFence = container_of(psCb, struct PVR_FENCE, sFenceCb);
+
+	if (WARN_ON_ONCE(is_pvr_fence(psFence)))
+		return;
+
+	PVRSyncSWCompleteOp(psPVRFence->psSyncData->psSyncInfo->psBase);
+
+	PVR_FENCE_TRACE(&psPVRFence->sBase,
+			"foreign fence %llu#%d signalled (%s)\n",
+			psPVRFence->psFenceCtx->ui64FenceCtx,
+			psPVRFence->psFenceCtx->sSeqno, psPVRFence->pName);
+
+	psPVRFence->psFenceCtx->bSyncHasSignaled = IMG_TRUE;
+
+	/* Drop the reference on the base fence */
+	dma_fence_put(&psPVRFence->sBase);
+}
+
+/**
+ * pvr_fence_create_from_fence - creates a PVR fence from a fence
+ * @fctx: PVR fence context on which the PVR fence should be created
+ * @fence: fence from which the PVR fence should be created
+ * @name: PVR fence name (used for debugging)
+ *
+ * Creates a PVR fence from an existing fence. If the fence is a foreign fence,
+ * i.e. one that doesn't originate from a PVR fence context, then a new PVR
+ * fence will be created. Otherwise, a reference will be taken on the underlying
+ * fence and the PVR fence will be returned.
+ *
+ * Once the fence is finished with pvr_fence_destroy should be called.
+ *
+ * Returns NULL if a PVR fence cannot be created.
+ */
+struct PVR_FENCE *
+pvr_fence_create_from_fence(struct PVR_FENCE_CONTEXT *psFenceCtx,
+			    struct dma_fence *psFence,
+			    const char *name)
+{
+	struct PVR_FENCE *psPVRFence;
+	unsigned int seqno;
+	unsigned long flags;
+	struct PVR_SYNC_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	int err;
+
+	psPVRFence = kzalloc(sizeof(*psPVRFence), GFP_KERNEL);
+	if (!psPVRFence)
+		return NULL;
+
+	psPVRFence->psSyncData = kmalloc(sizeof(struct PVR_SYNC_DATA), GFP_KERNEL);
+	if (!psPVRFence->psSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_SYNC_DATA",
+								__func__));
+		err = -ENOMEM;
+		goto err_free_pvr_fence;
+	}
+
+	psKernelSyncInfo = kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if (!psKernelSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+								"PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		err = -ENOMEM;
+		goto err_free_pvr_fence;
+	}
+
+	/* Allocate a "shadow" SYNCINFO for this foreign fence and set it up to be
+	 * completed by the callback.
+	 */
+	err = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+								   gsSyncServicesConnection.hDevMemContext,
+								   &psKernelSyncInfo->psBase);
+	if(err != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate syncinfo", __func__));
+		goto err_free_sync_data;
+	}
+
+	PVRSyncSWTakeOp(psKernelSyncInfo->psBase);
+
+	INIT_LIST_HEAD(&psPVRFence->sFenceHead);
+	INIT_LIST_HEAD(&psPVRFence->sSignalHead);
+	psPVRFence->psFenceCtx = psFenceCtx;
+	psPVRFence->pName = name;
+	psPVRFence->psFence = psFence;
+	psPVRFence->psSyncData->psSyncInfo = psKernelSyncInfo;
+	/*
+	 * We use the base fence to refcount the PVR fence and to do the
+	 * necessary clean up once the refcount drops to 0.
+	 */
+	seqno = pvr_fence_context_seqno_next(psFenceCtx);
+	dma_fence_init(&psPVRFence->sBase, &pvr_fence_foreign_ops, &psFenceCtx->sLock,
+		       psFenceCtx->ui64FenceCtx, seqno);
+
+	/*
+	 * Take an extra reference on the base fence that gets dropped when the
+	 * foreign fence is signalled.
+	 */
+	dma_fence_get(&psPVRFence->sBase);
+
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_add_tail(&psPVRFence->sFenceHead, &psFenceCtx->sFenceList);
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+	kref_get(&psFenceCtx->sRef);
+
+	PVR_FENCE_TRACE(&psPVRFence->sBase,
+			"created fence from foreign fence %llu#%d (%s)\n",
+			(u64) psPVRFence->psFenceCtx->ui64FenceCtx,
+			psPVRFence->psFenceCtx->sSeqno, name);
+
+	err = dma_fence_add_callback(psFence, &psPVRFence->sFenceCb,
+				     pvr_fence_foreign_signal_sync);
+	if (err) {
+		if (err != -ENOENT)
+			goto err_put_ref;
+
+		PVRSyncSWCompleteOp(psKernelSyncInfo->psBase);
+		PVR_FENCE_TRACE(&psPVRFence->sBase,
+				"foreign fence %llu#%d already signaled (%s)\n",
+				(u64) psPVRFence->psFenceCtx->ui64FenceCtx,
+				psPVRFence->psFenceCtx->sSeqno,
+				name);
+		dma_fence_put(&psPVRFence->sBase);
+	}
+
+
+	return psPVRFence;
+
+err_put_ref:
+	kref_put(&psFenceCtx->sRef, pvr_fence_context_destroy_kref);
+	spin_lock_irqsave(&psFenceCtx->sListLock, flags);
+	list_del(&psPVRFence->sFenceHead);
+	spin_unlock_irqrestore(&psFenceCtx->sListLock, flags);
+	PVRSyncSWCompleteOp(psKernelSyncInfo->psBase);
+	PVRSRVReleaseSyncInfoKM(psKernelSyncInfo->psBase);
+err_free_sync_data:
+	kfree(psPVRFence->psSyncData);
+err_free_pvr_fence:
+	kfree(psPVRFence);
+	return NULL;
+}
+
+/**
+ * pvr_fence_destroy - destroys a PVR fence
+ * @pvr_fence: PVR fence to destroy
+ *
+ * Destroys a PVR fence. Upon return, the PVR fence may still exist if something
+ * else still references the underlying fence, e.g. a reservation object, or if
+ * software signalling has been enabled and the fence hasn't yet been signalled.
+ */
+void
+pvr_fence_destroy(struct PVR_FENCE *psPVRFence)
+{
+	PVR_FENCE_TRACE(&psPVRFence->sBase, "destroyed fence (%s)\n", psPVRFence->pName);
+
+	dma_fence_put(&psPVRFence->sBase);
+}
+
+static bool is_pvr_timeline(struct file *psFile)
+{
+	return psFile->f_op == &pvr_sync_fops;
+}
+
+static struct PVR_SYNC_TIMELINE *pvr_sync_timeline_fget(int fd)
+{
+	struct file *psFile = fget(fd);
+
+	if (!psFile)
+		return NULL;
+
+	if (!is_pvr_timeline(psFile)) {
+		fput(psFile);
+		return NULL;
+	}
+
+	return psFile->private_data;
+}
+
+static void pvr_sync_timeline_fput(struct PVR_SYNC_TIMELINE *psTimeLine)
+{
+	fput(psTimeLine->psFile);
+}
+
+static int PVRSyncOpen(struct inode *inode, struct file *psFile)
+{
+	struct PVR_FENCE_CONTEXT *psFenceCtx;
+	struct PVR_SYNC_TIMELINE *psTimeline;
+	char task_comm[TASK_COMM_LEN];
+	int err = -ENOMEM;
+
+	get_task_comm(task_comm, current);
+
+	psTimeline = kzalloc(sizeof(*psTimeline), GFP_KERNEL);
+	if (!psTimeline)
+		goto err_out;
+
+	strlcpy(psTimeline->name, task_comm, sizeof(psTimeline->name));
+
+	psFenceCtx =  pvr_fence_context_create(psTimeline->name);
+	if (!psFenceCtx) {
+		PVR_DPF((PVR_DBG_ERROR, "pvr_fence: %s: pvr_fence_context_create failed\n", __func__));
+		goto err_free_timeline;
+	}
+
+	psTimeline->psSyncInfo = kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if(!psTimeline->psSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		goto err_free_fence;
+	}
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+	err = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+								   gsSyncServicesConnection.hDevMemContext,
+								   &psTimeline->psSyncInfo->psBase);
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (err != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate timeline syncinfo",
+								__func__));
+		goto err_free_syncinfo;
+	}
+
+	psTimeline->psFenceCtx = psFenceCtx;
+	psTimeline->psFile = psFile;
+
+	psFile->private_data = psTimeline;
+	err = 0;
+err_out:
+	return err;
+err_free_syncinfo:
+	kfree(psTimeline->psSyncInfo);
+err_free_fence:
+	pvr_fence_context_destroy(psFenceCtx);
+err_free_timeline:
+	kfree(psTimeline);
+	goto err_out;
+}
+
+static int PVRSyncRelease(struct inode *inode, struct file *psFile)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline = psFile->private_data;
+
+	if (psTimeline->pSWTimeline)
+	{
+		/* This makes sure any outstanding SW syncs are marked as
+		 * complete at timeline close time. Otherwise it'll leak the
+		 * timeline (as outstanding fences hold a ref) and possibly
+		 * wedge the system is something is waiting on one of those
+		 * fences
+		 */
+		pvr_counting_fence_timeline_force_complete(psTimeline->pSWTimeline);
+		pvr_counting_fence_timeline_put(psTimeline->pSWTimeline);
+
+		/*
+		 * pvr_fence_context_destroy can not be called for sw timeline -
+		 * otherwise it leads to double list_del on sFenceCtxList
+		 */
+		kref_put(&psTimeline->psFenceCtx->sRef, pvr_fence_context_destroy_kref);
+	} else {
+		pvr_fence_context_destroy(psTimeline->psFenceCtx);
+	}
+
+	PVRSyncReleaseSyncInfo(psTimeline->psSyncInfo);
+	kfree(psTimeline);
+
+	return 0;
+}
+
+static long PVRSyncIOCTLCreate(struct PVR_SYNC_TIMELINE *psTimeline, void __user *pvData)
+{
+	struct PVR_SYNC_KERNEL_SYNC_INFO *psProvidedSyncInfo = NULL;
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+	struct PVR_SYNC_CREATE_IOCTL_DATA sData;
+	int err = -EFAULT, iFd;
+	struct PVR_FENCE *psPVRFence;
+	struct sync_file *psSyncfile;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0))
+	iFd = get_unused_fd_flags(0);
+#else
+	iFd = get_unused_fd();
+#endif
+	if (iFd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+								__func__, iFd));
+		goto err_out;
+	}
+
+	if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (sData.allocdSyncInfo < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Requested to create a fence from "
+								" an invalid alloc'd fd (%d)", __func__,
+								sData.allocdSyncInfo));
+		goto err_put_fd;
+	}
+
+	psAllocSyncData = PVRSyncAllocFDGet(sData.allocdSyncInfo);
+	if (!psAllocSyncData) {
+		PVR_DPF((PVR_DBG_ERROR, "pvr_fence: %s: Failed to open supplied file fd (%d)\n",
+			__func__, sData.allocdSyncInfo));
+		err = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+		goto err_put_fd;
+	}
+
+	/* Move the psSyncInfo to the newly created sync, to avoid attempting
+	 * to create multiple syncs from the same allocation.
+	 */
+	psProvidedSyncInfo = psAllocSyncData->psSyncInfo;
+	psAllocSyncData->psSyncInfo = NULL;
+
+	if (psProvidedSyncInfo == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Alloc'd sync info is null - "
+								"possibly already CREATEd?", __func__));
+		fput(psAllocSyncData->psFile);
+		goto err_put_fd;
+	}
+	fput(psAllocSyncData->psFile);
+
+	sData.name[sizeof(sData.name) - 1] = '\0';
+
+	psPVRFence = pvr_fence_create(psAllocSyncData->psTimeline->psFenceCtx, sData.name, psProvidedSyncInfo);
+	if (!psPVRFence)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "pvr_fence: %s: Failed to create new pvr_fence\n", __func__));
+		err = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto err_put_fd;
+	}
+
+	psPVRFence->psSyncData->ui32WOPSnapshot = psAllocSyncData->psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending;
+
+	psSyncfile = sync_file_create(&psPVRFence->sBase);
+	if (!psSyncfile) {
+		PVR_DPF((PVR_DBG_ERROR, ": %s: Failed to create sync_file\n", __func__));
+		err = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto err_destroy_fence;
+	}
+
+	sData.fence = iFd;
+
+	if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+	{
+		goto err_destroy_fence;
+	}
+
+	if (copy_to_user(pvData, &sData, sizeof(sData)))
+	{
+		goto err_destroy_fence;
+	}
+
+	/* If the fence is a 'real' one, its signal status will be updated by
+	 * the MISR calling PVRSyncUpdateAllSyncs(). However, if we created
+	 * a 'fake' fence (for power optimization reasons) it has already
+	 * completed, and needs to be marked signalled (as the MISR will
+	 * never run for 'fake' fences).
+	 */
+	if(psProvidedSyncInfo->psBase->psSyncData->ui32WriteOpsPending == 0)
+	{
+		psPVRFence->psFenceCtx->bSyncHasSignaled = IMG_TRUE;
+	}
+
+	DPF("Create: WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X F=%p %s",
+		psProvidedSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psProvidedSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psProvidedSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+		psPVRFence, sData.name);
+
+	fd_install(iFd, psSyncfile->file);
+	err = 0;
+err_out:
+	return err;
+
+err_destroy_fence:
+	pvr_fence_destroy(psPVRFence);
+err_put_fd:
+	put_unused_fd(iFd);
+	goto err_out;
+}
+
+static long PVRSyncIOCTLRename(struct PVR_SYNC_TIMELINE *psTimeline, void __user *user_data)
+{
+	int err = 0;
+	struct PVR_SYNC_RENAME_IOCTL_DATA data;
+
+	if (!access_ok(VERIFY_READ, user_data, sizeof(data))) {
+		err = -EFAULT;
+		goto err;
+	}
+
+	if (copy_from_user(&data, user_data, sizeof(data))) {
+		err = -EFAULT;
+		goto err;
+	}
+
+	data.szName[sizeof(data.szName) - 1] = '\0';
+	strlcpy(psTimeline->name, data.szName, sizeof(psTimeline->name));
+
+err:
+	return err;
+}
+
+static long PVRSyncIOCTLForceSw(struct PVR_SYNC_TIMELINE *psTimeline, void **private_data)
+{
+	/* Already in SW mode? */
+	if (psTimeline->pSWTimeline)
+		return 0;
+
+	/* Create a sw_sync timeline with the old GPU timeline's name */
+	psTimeline->pSWTimeline = pvr_counting_fence_timeline_create(psTimeline->name);
+
+	/* Don't add SW timeline to global timeline list */
+	mutex_lock(&gFenceCtxListLock);
+	list_del(&psTimeline->psFenceCtx->sFenceCtxList);
+	mutex_unlock(&gFenceCtxListLock);
+
+	if (!psTimeline->pSWTimeline)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static long PVRSyncIOCTLCreateSwFence(struct PVR_SYNC_TIMELINE *psTimeline, void __user *user_data)
+{
+	struct sw_sync_create_fence_data sData;
+	struct sync_file *psSyncFile;
+	int fd = get_unused_fd_flags(0);
+	struct dma_fence *psFence;
+	int err = -EFAULT;
+
+	if (fd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"pvr_fence: %s: Failed to find unused fd (%d)", __func__, fd));
+		goto err_out;
+	}
+
+	if (copy_from_user(&sData, user_data, sizeof(sData)))
+	{
+		PVR_DPF((PVR_DBG_ERROR,"pvr_fence: %s: Failed copy from user", __func__));
+		goto err_put_fd;
+	}
+
+	psFence = pvr_counting_fence_create(psTimeline->pSWTimeline, sData.value);
+	if (!psFence)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"pvr_fence: %s: Failed to create a sync point (%d)", __func__, fd));
+		err = -ENOMEM;
+		goto err_put_fd;
+	}
+
+	psSyncFile = sync_file_create(psFence);
+	if (!psSyncFile)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"pvr_fence: %s: Failed to create a sync point (%d)", __func__, fd));
+		 err = -ENOMEM;
+		goto err_put_fence;
+	}
+
+	sData.fence = fd;
+
+	if (copy_to_user(user_data, &sData, sizeof(sData)))
+	{
+		PVR_DPF((PVR_DBG_ERROR,"pvr_fence: %s: Failed copy to user", __func__));
+		goto err_put_fence;
+	}
+
+	fd_install(fd, psSyncFile->file);
+	err = 0;
+err_out:
+	return err;
+err_put_fence:
+	dma_fence_put(psFence);
+err_put_fd:
+	put_unused_fd(fd);
+	goto err_out;
+}
+
+static long PVRSyncIOCTLSWInc(struct PVR_SYNC_TIMELINE *psTimeline, void __user *user_data)
+{
+	u32 value;
+
+	if (copy_from_user(&value, user_data, sizeof(value)))
+		return -EFAULT;
+
+	pvr_counting_fence_timeline_inc(psTimeline->pSWTimeline, value);
+	return 0;
+}
+
+static int PVRSyncFenceAllocRelease(struct inode *inode, struct file *file)
+{
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData = file->private_data;
+
+	if(psAllocSyncData->psSyncInfo)
+	{
+
+		DPF("R(a): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+			psAllocSyncData->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+			psAllocSyncData->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+			psAllocSyncData->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+		PVRSyncReleaseSyncInfo(psAllocSyncData->psSyncInfo);
+		psAllocSyncData->psSyncInfo = NULL;
+	}
+
+	kfree(psAllocSyncData);
+	return 0;
+}
+
+static const struct file_operations gsSyncFenceAllocFOps =
+{
+	.release = PVRSyncFenceAllocRelease,
+};
+
+struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd)
+{
+	struct file *file = fget(fd);
+	if (!file)
+		return NULL;
+	if (file->f_op != &gsSyncFenceAllocFOps)
+		goto err;
+	return file->private_data;
+err:
+	fput(file);
+	return NULL;
+}
+
+static long
+PVRSyncIOCTLAlloc(struct PVR_SYNC_TIMELINE *psTimeline, void __user *pvData)
+{
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+	int err = -EFAULT, iFd;
+	struct PVR_SYNC_ALLOC_IOCTL_DATA sData;
+	PVRSRV_SYNC_DATA *psSyncData;
+	struct file *psFile;
+	PVRSRV_ERROR eError;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0))
+	iFd = get_unused_fd_flags(0);
+#else
+	iFd = get_unused_fd();
+#endif
+	if (iFd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+					__func__, iFd));
+		goto err_out;
+	}
+
+	if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	psAllocSyncData = kmalloc(sizeof(struct PVR_ALLOC_SYNC_DATA), GFP_KERNEL);
+	if (!psAllocSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_ALLOC_SYNC_DATA", __func__));
+		err = -ENOMEM;
+		goto err_put_fd;
+	}
+
+	psAllocSyncData->psSyncInfo = kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if (!psAllocSyncData->psSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		err = -ENOMEM;
+		goto err_free_alloc_sync_data;
+	}
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+	eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+				       gsSyncServicesConnection.hDevMemContext,
+								   &psAllocSyncData->psSyncInfo->psBase);
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to alloc syncinfo (%d)", __func__, eError));
+		err = -ENOMEM;
+		goto err_free_sync_info;
+	}
+
+	psFile = anon_inode_getfile("pvr_fence_alloc", &gsSyncFenceAllocFOps, psAllocSyncData, 0);
+	if (!psFile)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create anon inode", __func__));
+		err = -ENOMEM;
+		goto err_release_sync_info;
+	}
+
+	sData.fence = iFd;
+
+	/* Check if this timeline looks idle. If there are still TQs running
+	 * on it, userspace shouldn't attempt any kind of power optimization
+	 * (e.g. it must not dummy-process GPU fences).
+	 *
+	 * Determining idleness here is safe because the ALLOC and CREATE
+	 * pvr_sync ioctls must be called under the gralloc module lock, so
+	 * we can't be creating another new fence op while we are still
+	 * processing this one.
+	 *
+	 * Take the bridge lock anyway so we can be sure that we read the
+	 * timeline sync's pending value coherently. The complete value may
+	 * be modified by the GPU, but worse-case we will decide we can't do
+	 * the power optimization and will still be correct.
+	 */
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	psSyncData = psTimeline->psSyncInfo->psBase->psSyncData;
+	if(psSyncData->ui32WriteOpsPending == psSyncData->ui32WriteOpsComplete)
+	{
+		sData.bTimelineIdle = IMG_TRUE;
+	}
+	else
+	{
+		sData.bTimelineIdle = IMG_FALSE;
+	}
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+		goto err_release_file;
+
+	if (copy_to_user(pvData, &sData, sizeof(sData)))
+		goto err_release_file;
+
+	psAllocSyncData->psTimeline = psTimeline;
+	psAllocSyncData->psFile = psFile;
+
+	DPF("A( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+		psAllocSyncData->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psAllocSyncData->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psAllocSyncData->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+	fd_install(iFd, psFile);
+	err = 0;
+err_out:
+	return err;
+err_release_sync_info:
+	PVRSRVReleaseSyncInfoKM(psAllocSyncData->psSyncInfo->psBase);
+err_free_sync_info:
+	kfree(psAllocSyncData->psSyncInfo);
+err_free_alloc_sync_data:
+	kfree(psAllocSyncData);
+err_put_fd:
+	put_unused_fd(iFd);
+	goto err_out;
+err_release_file:
+	fput(psFile);
+	put_unused_fd(iFd);
+	goto err_out;
+}
+
+static long
+PVRSyncIOCTLDebug(struct PVR_SYNC_TIMELINE *psTimeline, void __user *pvData)
+{
+	struct PVR_SYNC_DEBUG_IOCTL_DATA sData;
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	struct dma_fence *psFence;
+	struct PVR_FENCE *psPVRFence;
+	int err = -EFAULT;
+	PVR_SYNC_DEBUG *psMetaData;
+
+	if(!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_out;
+
+	if(copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_out;
+
+	psMetaData = &sData.sSync[0].sMetaData;
+
+	psFence = sync_file_get_fence(sData.iFenceFD);
+	if(!psFence)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get fence from fd", __func__));
+		goto err_out;
+	}
+
+	psPVRFence = to_pvr_fence(psFence);
+	/* Don't dump foreign fence */
+	if(!psPVRFence)
+		return 0;
+
+	psKernelSyncInfo = psPVRFence->psSyncData->psSyncInfo->psBase;
+	PVR_ASSERT(psKernelSyncInfo != NULL);
+
+	/* The sync refcount is valid as long as the FenceFD stays open,
+	 * so we can access it directly without worrying about it being
+	 * freed.
+	 */
+	sData.sSync[0].sSyncData = *psKernelSyncInfo->psSyncData;
+
+	psMetaData->ui32WriteOpsPendingSnapshot = psPVRFence->psSyncData->ui32WOPSnapshot;
+
+	dma_fence_put(psFence);
+
+	sData.ui32NumPoints = 1;
+
+	if(!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+		goto err_out;
+
+	if(copy_to_user(pvData, &sData, sizeof(sData)))
+		goto err_out;
+
+	err = 0;
+err_out:
+	return err;
+}
+
+static long
+PVRSyncIOCTL(struct file *file, unsigned int cmd, unsigned long __user arg)
+{
+	void __user *user_data = (void __user *)arg;
+	long err = -ENOTTY;
+	struct PVR_SYNC_TIMELINE *psTimeline = file->private_data;
+	bool is_sw_timeline = psTimeline->pSWTimeline != NULL;
+
+	if (!is_sw_timeline) {
+
+		switch (cmd) {
+		case PVR_SYNC_IOC_CREATE_FENCE:
+			err = PVRSyncIOCTLCreate(psTimeline, user_data);
+			break;
+		case PVR_SYNC_IOC_DEBUG_FENCE:
+			err = PVRSyncIOCTLDebug(psTimeline, user_data);
+			break;
+		case PVR_SYNC_IOC_ALLOC_FENCE:
+			err = PVRSyncIOCTLAlloc(psTimeline, user_data);
+			break;
+		case PVR_SYNC_IOC_RENAME:
+			err = PVRSyncIOCTLRename(psTimeline, user_data);
+			break;
+		case PVR_SYNC_IOC_FORCE_SW_ONLY:
+			err = PVRSyncIOCTLForceSw(psTimeline, &file->private_data);
+			break;
+		default:
+			err = -ENOTTY;
+		}
+	} else {
+
+		switch (cmd) {
+		case SW_SYNC_IOC_CREATE_FENCE:
+			err = PVRSyncIOCTLCreateSwFence(psTimeline, user_data);
+			break;
+		case SW_SYNC_IOC_INC:
+			err = PVRSyncIOCTLSWInc(psTimeline, user_data);
+			break;
+		default:
+			err = -ENOTTY;
+		}
+	}
+
+	return err;
+}
+
+static void PVRSyncWorkQueueFunction(struct work_struct *data)
+{
+	PVRSRV_DEVICE_NODE *psDevNode =
+		(PVRSRV_DEVICE_NODE*)gsSyncServicesConnection.hDevCookie;
+	struct list_head sFreeList, *psEntry, *n;
+	unsigned long flags;
+
+	/* We lock the bridge mutex here for two reasons.
+	 *
+	 * Firstly, the SGXScheduleProcessQueuesKM and PVRSRVReleaseSyncInfoKM
+	 * functions require that they are called under lock. Multiple threads
+	 * into services are not allowed.
+	 *
+	 * Secondly, we need to ensure that when processing the defer-free list,
+	 * the PVRSyncIsSyncInfoInUse() function is called *after* any freed
+	 * sync was attached as a HW dependency (had ROP/ROP2 taken). This is
+	 * because for 'foreign' sync timelines we allocate a new object and
+	 * mark it for deletion immediately. If the 'foreign' sync_pt signals
+	 * before the kick ioctl has completed, we can block it from being
+	 * prematurely freed by holding the bridge mutex.
+	 *
+	 * NOTE: This code relies on the assumption that we can acquire a
+	 * spinlock while a mutex is held and that other users of the spinlock
+	 * do not need to hold the bridge mutex.
+	 */
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	/* A completed SW operation may un-block the GPU */
+	SGXScheduleProcessQueuesKM(psDevNode);
+
+	/* We can't call PVRSRVReleaseSyncInfoKM directly in this loop because
+	 * that will take the mmap mutex. We can't take mutexes while we have
+	 * this list locked with a spinlock. So move all the items we want to
+	 * free to another, local list (no locking required) and process it
+	 * in a second loop.
+	 */
+
+	INIT_LIST_HEAD(&sFreeList);
+	spin_lock_irqsave(&gSyncInfoFreeListLock, flags);
+	list_for_each_safe(psEntry, n, &gSyncInfoFreeList)
+	{
+		struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+			container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		if(!PVRSyncIsSyncInfoInUse(psSyncInfo->psBase))
+			list_move_tail(psEntry, &sFreeList);
+
+	}
+	spin_unlock_irqrestore(&gSyncInfoFreeListLock, flags);
+
+	list_for_each_safe(psEntry, n, &sFreeList)
+	{
+		struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+			container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		list_del(psEntry);
+
+		DPF("F(d): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+			psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+		PVRSRVReleaseSyncInfoKM(psSyncInfo->psBase);
+		psSyncInfo->psBase = NULL;
+
+		kfree(psSyncInfo);
+	}
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+static const struct file_operations pvr_sync_fops = {
+	.owner          = THIS_MODULE,
+	.open           = PVRSyncOpen,
+	.release        = PVRSyncRelease,
+	.unlocked_ioctl = PVRSyncIOCTL,
+	.compat_ioctl   = PVRSyncIOCTL,
+};
+
+static struct miscdevice pvr_sync_device = {
+	.minor          = MISC_DYNAMIC_MINOR,
+	.name           = "pvr_sync",
+	.fops           = &pvr_sync_fops,
+};
+
+IMG_INTERNAL
+int PVRSyncDeviceInit(void)
+{
+	int err = -1;
+
+	if(PVRSyncInitServices() != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise services",
+								__func__));
+		goto err_out;
+	}
+
+	gsSyncServicesConnection.psForeignFenceCtx  = pvr_fence_context_create("foreign_sync");
+	if (!gsSyncServicesConnection.psForeignFenceCtx)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"pvr_fence: %s: Failed to create foreign sync context\n",
+			__func__));
+		err = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto err_out;
+	}
+
+	gpsWorkQueue = create_freezable_workqueue("pvr_sync_workqueue");
+	if(!gpsWorkQueue)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create pvr_sync workqueue", __func__));
+		goto err_deinit_services;
+	}
+
+	INIT_WORK(&gsWork, PVRSyncWorkQueueFunction);
+
+	err = misc_register(&pvr_sync_device);
+	if(err)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to register pvr_sync misc "
+								"device (err=%d)", __func__, err));
+		goto err_destory_wq;
+	}
+	err = PVRSRV_OK;
+
+err_out:
+	return err;
+err_destory_wq:
+	destroy_workqueue(gpsWorkQueue);
+err_deinit_services:
+	pvr_fence_context_destroy(gsSyncServicesConnection.psForeignFenceCtx);
+	PVRSyncCloseServices();
+	goto err_out;
+}
+
+void PVRSyncDeviceDeInit(void)
+{
+	pvr_fence_cleanup();
+	misc_deregister(&pvr_sync_device);
+	pvr_fence_context_destroy(gsSyncServicesConnection.psForeignFenceCtx);
+	destroy_workqueue(gpsWorkQueue);
+	PVRSyncCloseServices();
+}
+
+struct PVR_COUNTING_FENCE_TIMELINE *pvr_sync_get_sw_timeline(int fd)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline;
+	struct PVR_COUNTING_FENCE_TIMELINE *psSwTimeline = NULL;
+
+	psTimeline = pvr_sync_timeline_fget(fd);
+	if (!psTimeline)
+		return NULL;
+
+	psSwTimeline = pvr_counting_fence_timeline_get(psTimeline->pSWTimeline);
+
+	pvr_sync_timeline_fput(psTimeline);
+	return psSwTimeline;
+}
+
+IMG_BOOL
+ExpandAndDeDuplicateFenceSyncs(IMG_UINT32 ui32NumSyncs,
+							   IMG_HANDLE aiFenceFds[],
+							   IMG_UINT32 ui32SyncPointLimit,
+							   struct dma_fence *apsFence[],
+							   IMG_UINT32 *pui32NumRealSyncs,
+							   PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[])
+{
+	IMG_UINT32 i, ui32FenceIndex = 0;
+	IMG_BOOL bRet = IMG_TRUE;
+
+	*pui32NumRealSyncs = 0;
+
+	for(i = 0; i < ui32NumSyncs; i++)
+	{
+		struct PVR_FENCE *psPVRFence;
+
+		/* Skip any invalid fence file descriptors without error */
+		if((IMG_INT32)aiFenceFds[i] < 0)
+			continue;
+
+		/* By converting a file descriptor to a struct sync_fence, we are
+		 * taking a reference on the fence. We don't want the fence to go
+		 * away until we have submitted the command, even if it signals
+		 * before we dispatch the command, or the timeline(s) are destroyed.
+		 *
+		 * This reference should be released by the caller of this function
+		 * once hardware operations have been scheduled on the GPU sync_pts
+		 * participating in this fence. When our MISR is scheduled, the
+		 * defer-free list will be processed, cleaning up the SYNCINFO.
+		 *
+		 * Note that this reference *isn't* enough for non-GPU sync_pts.
+		 * We'll take another reference on the fence for those operations
+		 * later (the life-cycle requirements there are totally different).
+		 *
+		 * Fence lookup may fail here if the fd became invalid since it was
+		 * patched in userspace. That's really a userspace driver bug, so
+		 * just fail here instead of not synchronizing.
+		 */
+		apsFence[ui32FenceIndex] = sync_file_get_fence((IMG_INT32)aiFenceFds[i]);
+		if(!apsFence[ui32FenceIndex])
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get fence from fd=%d",
+									__func__, (IMG_SIZE_T)aiFenceFds[i]));
+			bRet = IMG_FALSE;
+			goto err_out;
+		}
+
+		/* If this fence has any points from foreign timelines, we need to
+		 * allocate a 'shadow' SYNCINFO and update it in software ourselves,
+		 * so the ukernel can test the readiness of the dependency.
+		 *
+		 * It's tempting to just handle all fences like this (since most of
+		 * the time they *will* be merged with sw_sync) but such 'shadow'
+		 * syncs are slower. This is because we need to wait for the MISR to
+		 * schedule to update the GPU part of the fence (normally the ukernel
+		 * would be able to make the update directly).
+		 */
+		psPVRFence = to_pvr_fence(apsFence[ui32FenceIndex]);
+		if(!psPVRFence)
+		{
+
+			psPVRFence = pvr_fence_create_from_fence(gsSyncServicesConnection.psForeignFenceCtx, apsFence[ui32FenceIndex], "foreign");
+			if(psPVRFence)
+			{
+				if(!AddSyncInfoToArray(psPVRFence->psSyncData->psSyncInfo->psBase, ui32SyncPointLimit,
+									   pui32NumRealSyncs, apsSyncInfo))
+				{
+					/* Soft-fail. Stop synchronizing. */
+					goto err_out;
+				}
+			}
+		}
+		else
+		{
+			if(!AddSyncInfoToArray(psPVRFence->psSyncData->psSyncInfo->psBase, ui32SyncPointLimit, pui32NumRealSyncs, apsSyncInfo))
+					goto err_out;
+		}
+		ui32FenceIndex++;
+	}
+
+err_out:
+	return bRet;
+}
+
+PVRSRV_ERROR PVRSyncInitServices(void)
+{
+	IMG_BOOL bCreated, bShared[PVRSRV_MAX_CLIENT_HEAPS];
+	PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+	IMG_UINT32 ui32ClientHeapCount = 0;
+	PVRSRV_PER_PROCESS_DATA	*psPerProc;
+	PVRSRV_ERROR eError;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	gsSyncServicesConnection.ui32Pid = OSGetCurrentProcessIDKM();
+
+	eError = PVRSRVProcessConnect(gsSyncServicesConnection.ui32Pid, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVProcessConnect failed",
+								__func__));
+		goto err_unlock;
+	}
+
+	psPerProc = PVRSRVFindPerProcessData();
+	if (!psPerProc)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVFindPerProcessData failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	eError = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_SGX,
+									   &gsSyncServicesConnection.hDevCookie);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVAcquireDeviceDataKM failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	if (!gsSyncServicesConnection.hDevCookie)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: hDevCookie is NULL", __func__));
+		goto err_disconnect;
+	}
+
+	eError = PVRSRVCreateDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+						psPerProc,
+											&gsSyncServicesConnection.hDevMemContext,
+											&ui32ClientHeapCount,
+											&sHeapInfo[0],
+											&bCreated,
+											&bShared[0]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVCreateDeviceMemContextKM failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	if (!gsSyncServicesConnection.hDevMemContext)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: hDevMemContext is NULL", __func__));
+		goto err_disconnect;
+	}
+
+err_unlock:
+	LinuxUnLockMutex(&gPVRSRVLock);
+	return eError;
+
+err_disconnect:
+	PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+	goto err_unlock;
+}
+
+void PVRSyncCloseServices(void)
+{
+	IMG_BOOL bDummy;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	PVRSRVDestroyDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+									gsSyncServicesConnection.hDevMemContext,
+									&bDummy);
+	gsSyncServicesConnection.hDevMemContext = NULL;
+	gsSyncServicesConnection.hDevCookie = NULL;
+
+	PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+	gsSyncServicesConnection.ui32Pid = 0;
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_fence.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_fence.h
new file mode 100644
index 0000000..f7e9b22
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_fence.h
@@ -0,0 +1,252 @@
+/*************************************************************************/ /*!
+@File
+@Title          PowerVR Linux fence interface
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#if !defined(__PVR_FENCE_H__)
+#define __PVR_FENCE_H__
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
+#include <linux/fence.h>
+#else
+#include <linux/dma-fence.h>
+#endif
+
+//#define PVR_FENCE_DEBUG 1
+
+struct PVR_SYNC_KERNEL_SYNC_INFO
+{
+	/* Base services sync info structure */
+	PVRSRV_KERNEL_SYNC_INFO	*psBase;
+
+	/* Sync points can go away when there are deferred hardware
+	 * operations still outstanding. We must not free the SYNC_INFO
+	 * until the hardware is finished, so we add it to a defer list
+	 * which is processed periodically ("defer-free").
+	 *
+	 * This is also used for "defer-free" of a timeline -- the process
+	 * may destroy its timeline or terminate abnormally but the HW could
+	 * still be using the sync object hanging off of the timeline.
+	 *
+	 * Note that the defer-free list is global, not per-timeline.
+	 */
+	struct list_head		sHead;
+};
+
+struct PVR_SYNC_DATA
+{
+	/* Every sync fence has a services sync object. This object is used
+	 * by the hardware to enforce ordering -- it is attached as a source
+	 * dependency to various commands.
+	 */
+	struct PVR_SYNC_KERNEL_SYNC_INFO	*psSyncInfo;
+
+	/* This is purely a debug feature. Record the WOP snapshot from the
+	 * timeline synchronization object when a new fence is created.
+	 */
+	IMG_UINT32				ui32WOPSnapshot;
+};
+
+/* A PVR_ALLOC_SYNC_DATA is used to back an allocated, but not yet created
+ * and inserted into a timeline, sync data. This is required as we must
+ * allocate the syncinfo to be passed down with the transfer task used to
+ * implement fences in the hardware.
+ */
+struct PVR_ALLOC_SYNC_DATA
+{
+	struct PVR_SYNC_KERNEL_SYNC_INFO	*psSyncInfo;
+
+	/* A link to the timeline is required to add a per-timeline sync
+	 * to the fence transfer task.
+	 */
+	struct PVR_SYNC_TIMELINE			*psTimeline;
+	struct file					*psFile;
+};
+
+/**
+ * PVR_FENCE_CONTEXT - PVR fence context used to create and manage PVR fences
+ * @sLock: protects the context and fences created on the context
+ * @pcName: fence context name (used for debugging)
+ * @ui64FenceCtx: fence context with which to associate fences
+ * @sSeqno: sequence number to use for the next fence
+ * @psFenceWq: work queue for signalled fence work
+ * @sSignalWork: work item used to signal fences when fence syncs are met
+ * @sListLock: protects the active and active foreign lists
+ * @sSignalList: list of fences waiting to be signalled
+ * @sFenceList: list of fences (used for debugging)
+ * @sDeferredFreeList: list of fences that we will free when we are no longer
+ * @sFenceCtxList: list of all fence context
+ * holding spinlocks.  The frees get implemented when an update fence is
+ * signalled or the context is freed.
+ */
+struct PVR_FENCE_CONTEXT
+{
+	spinlock_t sLock;
+	const char *pName;
+
+	/* True if a sync fence on the fence context has signaled */
+	IMG_BOOL bSyncHasSignaled;
+
+	IMG_UINT64 ui64FenceCtx;
+	atomic_t sSeqno;
+
+	struct workqueue_struct *psFenceWq;
+	struct work_struct sSignalWork;
+
+	spinlock_t sListLock;
+	struct list_head sSignalList;
+	struct list_head sFenceList;
+	struct list_head sDeferredFreeList;
+	struct list_head sFenceCtxList;
+
+	struct kref sRef;
+	struct workqueue_struct *psDestroyWq;
+	struct work_struct sDestroyWork;
+};
+
+/**
+ * PVR_FENCE - PVR fence that represents both native and foreign fences
+ * @sBase: fence structure
+ * @psFenceCtx: fence context on which this fence was created
+ * @pcName: fence name (used for debugging)
+ * @psFencefence: pointer to base fence structure or foreign fence
+ * @psSyncData: services sync data used by hardware
+ * @sFenceHead: entry on the context fence and deferred free list
+ * @sSignalHead: entry on the context signal list
+ * @sFenceCb: foreign fence callback to set the sync to signalled
+ */
+struct PVR_FENCE {
+	struct dma_fence sBase;
+	struct PVR_FENCE_CONTEXT *psFenceCtx;
+	const char *pName;
+
+	struct dma_fence *psFence;
+	struct PVR_SYNC_DATA *psSyncData;
+
+	struct list_head sFenceHead;
+	struct list_head sSignalHead;
+	struct dma_fence_cb sFenceCb;
+};
+
+/* This is the actual timeline metadata. We might keep this around after the
+ * base sync driver has destroyed the pvr_sync_timeline_wrapper object.
+ */
+struct PVR_SYNC_TIMELINE {
+	struct PVR_FENCE_CONTEXT *psFenceCtx;
+	struct file *psFile;
+	char name[32];
+	struct PVR_COUNTING_FENCE_TIMELINE *pSWTimeline;
+
+	/* Every timeline has a services sync object. This object must not
+	 * be used by the hardware to enforce ordering -- that's what the
+	 * per sync-point objects are for. This object is attached to every
+	 * TQ scheduled on the timeline and is primarily useful for debugging.
+	 */
+	struct PVR_SYNC_KERNEL_SYNC_INFO	*psSyncInfo;
+};
+
+extern const struct dma_fence_ops pvr_fence_ops;
+extern const struct dma_fence_ops pvr_fence_foreign_ops;
+
+static inline bool is_our_fence(struct PVR_FENCE_CONTEXT *psFenceCtx,
+				struct dma_fence *psFence)
+{
+	return (psFence->context == psFenceCtx->ui64FenceCtx);
+}
+
+static inline bool is_pvr_fence(struct dma_fence *psFence)
+{
+	return ((psFence->ops == &pvr_fence_ops) ||
+		(psFence->ops == &pvr_fence_foreign_ops));
+}
+
+static inline struct PVR_FENCE *to_pvr_fence(struct dma_fence *psFence)
+{
+	if (is_pvr_fence(psFence))
+		return container_of(psFence, struct PVR_FENCE, sBase);
+
+	return NULL;
+}
+
+struct PVR_FENCE_CONTEXT *pvr_fence_context_create(const char *pcName);
+void pvr_fence_context_destroy(struct PVR_FENCE_CONTEXT *psFenceCtx);
+
+struct PVR_FENCE *pvr_fence_create(struct PVR_FENCE_CONTEXT *fctx,
+				   const char *name, struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo);
+struct PVR_FENCE *pvr_fence_create_from_fence(struct PVR_FENCE_CONTEXT *psFenceCtx,
+					      struct dma_fence *psFence,
+					      const char *pcName);
+void pvr_fence_destroy(struct PVR_FENCE *psPvrFence);
+
+PVRSRV_ERROR PVRSyncInitServices(void);
+void PVRSyncCloseServices(void);
+
+IMG_BOOL ExpandAndDeDuplicateFenceSyncs(IMG_UINT32 ui32NumSyncs,
+							   IMG_HANDLE aiFenceFds[],
+							   IMG_UINT32 ui32SyncPointLimit,
+							   struct dma_fence *apsFence[],
+							   IMG_UINT32 *pui32NumRealSyncs,
+							   PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[]);
+
+struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd);
+
+struct PVR_COUNTING_FENCE_TIMELINE *pvr_sync_get_sw_timeline(int fd);
+
+static inline void pvr_fence_cleanup(void)
+{
+	/*
+	 * Ensure all PVR fence contexts have been destroyed, by flushing
+	 * the global workqueue.
+	 * For those versions of the DDK don't use PVR fences, this isn't
+	 * necessary, but should be harmless.
+	 */
+	flush_scheduled_work();
+}
+
+#if defined(PVR_FENCE_DEBUG)
+#define PVR_FENCE_CTX_TRACE(c, fmt, ...)                                   \
+	do {                                                               \
+		struct PVR_FENCE_CONTEXT *__fctx = (c);                    \
+		pr_err("c %llu: (PVR) " fmt, (u64) __fctx->ui64FenceCtx,  \
+		       ## __VA_ARGS__);                                    \
+	} while (0)
+#else
+#define PVR_FENCE_CTX_TRACE(c, fmt, ...)
+#endif
+
+#define PVR_FENCE_CTX_WARN(c, fmt, ...)                                    \
+	do {                                                               \
+		struct PVR_FENCE_CONTEXT *__fctx = (c);                    \
+		pr_warn("c %llu: (PVR) " fmt, (u64) __fctx->ui64FenceCtx, \
+			## __VA_ARGS__);                                   \
+	} while (0)
+
+#define PVR_FENCE_CTX_ERR(c, fmt, ...)                                     \
+	do {                                                               \
+		struct PVR_FENCE_CONTEXT *__fctx = (c);                    \
+		pr_err("c %llu: (PVR) " fmt, (u64) __fctx->ui64FenceCtx,  \
+		       ## __VA_ARGS__);                                    \
+	} while (0)
+
+#if defined(PVR_FENCE_DEBUG)
+#define PVR_FENCE_TRACE(f, fmt, ...)                                       \
+	FENCE_ERR(f, "(PVR) " fmt, ## __VA_ARGS__)
+#else
+#define PVR_FENCE_TRACE(f, fmt, ...)
+#endif
+
+#define PVR_FENCE_WARN(f, fmt, ...)                                        \
+	FENCE_WARN(f, "(PVR) " fmt, ## __VA_ARGS__)
+
+#define PVR_FENCE_ERR(f, fmt, ...)                                         \
+	FENCE_ERR(f, "(PVR) " fmt, ## __VA_ARGS__)
+
+#endif /* !defined(__PVR_FENCE_H__) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_linux_fence.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_linux_fence.c
new file mode 100644
index 0000000..dac4ba8
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_linux_fence.c
@@ -0,0 +1,1533 @@
+/*************************************************************************/ /*!
+@File
+@Title          Linux fence interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Linux module setup
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+
+#include "srvkm.h"
+#include "syscommon.h"
+#include "pvr_linux_fence.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/atomic.h>
+#include <linux/spinlock.h>
+#include <linux/dma-fence.h>
+#include <linux/reservation.h>
+#include <linux/list.h>
+
+#include "dmabuf.h"
+
+#define	BLOCKED_ON_READ		1
+#define	BLOCKED_ON_WRITE	2
+
+struct pvr_fence_context
+{
+	struct mutex mutex;
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+	IMG_HANDLE hNativeSync;
+	struct work_struct fence_work;
+	struct list_head fence_frame_list;
+	struct list_head fence_context_notify_list;
+	struct list_head fence_context_list;
+};
+
+struct pvr_fence_frame;
+
+struct pvr_blocking_fence
+{
+	struct dma_fence *fence;
+	struct dma_fence_cb cb;
+	struct pvr_fence_frame *pvr_fence_frame;
+	bool installed;
+};
+
+struct pvr_fence_frame
+{
+	struct list_head fence_frame_list;
+	struct pvr_fence_context *pvr_fence_context;
+	u32 tag;
+	bool is_dst;
+	IMG_UINT32 ui32ReadOpsPending;
+	IMG_UINT32 ui32ReadOps2Pending;
+	IMG_UINT32 ui32WriteOpsPending;
+	int blocked_on;
+	struct pvr_blocking_fence *blocking_fences;
+	unsigned blocking_fence_count;
+	atomic_t blocking_count;
+	struct dma_fence *fence_to_signal;
+	bool unblock;
+	bool have_blocking_fences;
+};
+
+struct pvr_fence
+{
+	struct dma_fence fence;
+	spinlock_t lock;
+};
+
+static LIST_HEAD(fence_context_list);
+static LIST_HEAD(fence_context_notify_list);
+static DEFINE_MUTEX(pvr_fence_mutex);
+
+static struct workqueue_struct *workqueue;
+static unsigned fence_context;
+static atomic_t fence_seqno = ATOMIC_INIT(0);
+static atomic_t fences_outstanding = ATOMIC_INIT(0);
+
+#if defined(DEBUG)
+static atomic_t fences_allocated = ATOMIC_INIT(0);
+static atomic_t fences_signalled = ATOMIC_INIT(0);
+static atomic_t callbacks_installed = ATOMIC_INIT(0);
+static atomic_t callbacks_called = ATOMIC_INIT(0);
+#endif
+
+#if defined(PVR_DRM_DRIVER_NAME)
+static const char *drvname = PVR_DRM_DRIVER_NAME;
+#else
+static const char *drvname = "pvr";
+#endif
+static const char *timeline_name = "PVR";
+
+static unsigned next_seqno(void)
+{
+	return atomic_inc_return(&fence_seqno) - 1;
+}
+
+static const char *get_driver_name(struct dma_fence *fence)
+{
+	return drvname;
+}
+
+static const char *get_timeline_name(struct dma_fence *fence)
+{
+	return timeline_name;
+}
+
+static bool enable_signaling(struct dma_fence *fence)
+{
+	return true;
+}
+
+static void release_fence(struct dma_fence *fence)
+{
+	struct pvr_fence *pvr_fence = container_of(fence, struct pvr_fence, fence);
+	kfree(pvr_fence);
+
+	atomic_dec(&fences_outstanding);
+}
+
+static struct dma_fence_ops fence_ops =
+{
+	.get_driver_name = get_driver_name,
+	.get_timeline_name = get_timeline_name,
+	.enable_signaling = enable_signaling,
+	.wait = dma_fence_default_wait,
+	.release = release_fence
+};
+
+static inline bool is_pvr_fence(const struct dma_fence *fence)
+{
+	return fence->ops == &fence_ops;
+}
+
+static struct dma_fence *create_fence_to_signal(struct pvr_fence_frame *pvr_fence_frame)
+{
+	struct pvr_fence *pvr_fence;
+	unsigned seqno = next_seqno();
+
+	pvr_fence = kmalloc(sizeof(*pvr_fence), GFP_KERNEL);
+	if (!pvr_fence)
+	{
+		return NULL;
+	}
+
+	spin_lock_init(&pvr_fence->lock);
+
+	dma_fence_init(&pvr_fence->fence, &fence_ops, &pvr_fence->lock, fence_context, seqno);
+
+	pvr_fence_frame->fence_to_signal = &pvr_fence->fence;
+
+#if defined(DEBUG)
+	atomic_inc(&fences_allocated);
+#endif
+	atomic_inc(&fences_outstanding);
+
+	return pvr_fence_frame->fence_to_signal;
+}
+
+static inline bool is_blocking_fence(const struct dma_fence *fence)
+{
+	return fence && !is_pvr_fence(fence);
+}
+
+static inline bool is_unsignalled_blocking_fence(const struct dma_fence *fence)
+{
+	return is_blocking_fence(fence) && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags);
+}
+
+static void signal_and_put_fence(struct pvr_fence_frame *pvr_fence_frame)
+{
+	if (pvr_fence_frame->fence_to_signal)
+	{
+		dma_fence_signal(pvr_fence_frame->fence_to_signal);
+		dma_fence_put(pvr_fence_frame->fence_to_signal);
+
+		pvr_fence_frame->fence_to_signal = NULL;
+
+#if defined(DEBUG)
+		atomic_inc(&fences_signalled);
+#endif
+	}
+}
+
+static void blocking_fence_signalled(struct dma_fence *fence, struct dma_fence_cb *cb)
+{
+	struct pvr_blocking_fence *pvr_blocking_fence = container_of(cb, struct pvr_blocking_fence, cb);
+	struct pvr_fence_frame *pvr_fence_frame = pvr_blocking_fence->pvr_fence_frame;
+	struct pvr_fence_context *pvr_fence_context = pvr_fence_frame->pvr_fence_context;
+
+	if (atomic_dec_and_test(&pvr_fence_frame->blocking_count))
+	{
+		queue_work(workqueue, &pvr_fence_context->fence_work);
+	}
+#if defined(DEBUG)
+	atomic_inc(&callbacks_called);
+#endif
+}
+
+static bool allocate_blocking_fence_storage(struct pvr_fence_frame *pvr_fence_frame, unsigned count)
+{
+	pvr_fence_frame->blocking_fences = kzalloc(count * sizeof(*pvr_fence_frame->blocking_fences), GFP_KERNEL);
+	if (pvr_fence_frame->blocking_fences)
+	{	
+		pvr_fence_frame->blocking_fence_count = count;
+		return true;
+	}
+	return false;
+}
+
+static void free_blocking_fence_storage(struct pvr_fence_frame *pvr_fence_frame)
+{
+	if (pvr_fence_frame->blocking_fence_count)
+	{
+		kfree(pvr_fence_frame->blocking_fences);
+		pvr_fence_frame->blocking_fence_count = 0;
+	}
+}
+
+static int install_and_get_blocking_fence(struct pvr_fence_frame *pvr_fence_frame, unsigned index, struct dma_fence *fence)
+{
+	struct pvr_blocking_fence *pvr_blocking_fence = &pvr_fence_frame->blocking_fences[index];
+	int ret;
+
+	BUG_ON(index >= pvr_fence_frame->blocking_fence_count);
+
+	pvr_blocking_fence->fence = fence;
+	pvr_blocking_fence->pvr_fence_frame = pvr_fence_frame;
+
+	atomic_inc(&pvr_fence_frame->blocking_count);
+
+	ret = dma_fence_add_callback(pvr_blocking_fence->fence,
+			&pvr_blocking_fence->cb,
+			blocking_fence_signalled);
+
+	pvr_blocking_fence->installed = !ret;
+	if (!pvr_blocking_fence->installed)
+	{
+		atomic_dec(&pvr_fence_frame->blocking_count);
+		return 1;
+	}
+	else
+	{
+		dma_fence_get(fence);
+#if defined(DEBUG)
+		atomic_inc(&callbacks_installed);
+#endif
+		return 0;
+	}
+}
+
+static void uninstall_and_put_blocking_fence(struct pvr_fence_frame *pvr_fence_frame, unsigned index)
+{
+	struct pvr_blocking_fence *pvr_blocking_fence = &pvr_fence_frame->blocking_fences[index];
+
+	BUG_ON(index >= pvr_fence_frame->blocking_fence_count);
+
+	if (pvr_blocking_fence->installed)
+	{
+		if (dma_fence_remove_callback(pvr_blocking_fence->fence, &pvr_blocking_fence->cb))
+		{
+			atomic_dec(&pvr_fence_frame->blocking_count);
+		}
+		dma_fence_put(pvr_blocking_fence->fence);
+	}
+}
+
+static inline int update_reservation_return_value(int ret, bool blocked_on_write)
+{
+	return ret < 0 ? ret : (ret ? 0 : (blocked_on_write ? BLOCKED_ON_WRITE : BLOCKED_ON_READ));
+}
+
+static int update_reservation_object_fences_dst(struct pvr_fence_frame *pvr_fence_frame,
+						struct reservation_object *resv)
+{
+	struct reservation_object_list *flist;
+	struct dma_fence *fence_to_signal;
+	unsigned shared_fence_count;
+	unsigned blocking_fence_count;
+	unsigned i;
+	int ret;
+
+	flist = reservation_object_get_list(resv);
+	shared_fence_count = flist ? flist->shared_count : 0;
+
+	/*
+	 * There were not any blocking fences when we originally checked
+	 * the reservation object, but there could be now, as the reservation
+	 * object lock was dropped in the meantime. Check the fences again,
+	 * and don't add our exclusive fence if there are blocking fences
+	 * now.
+	 */
+	if (!pvr_fence_frame->have_blocking_fences)
+	{
+		struct dma_fence *fence;
+
+		fence = reservation_object_get_excl(resv);
+		if (is_unsignalled_blocking_fence(fence))
+		{
+			return 0;
+		}
+
+		for (i = 0; i < shared_fence_count; i++)
+		{
+			fence = rcu_dereference_protected(flist->shared[i], reservation_object_held(resv));
+
+			if (is_unsignalled_blocking_fence(fence))
+			{
+				return 0;
+			}
+		}
+	}
+
+	fence_to_signal = create_fence_to_signal(pvr_fence_frame);
+	if (!fence_to_signal)
+	{
+		return -ENOMEM;
+	}
+
+	if (!pvr_fence_frame->have_blocking_fences)
+	{
+		reservation_object_add_excl_fence(resv, fence_to_signal);
+		return 0;
+	}
+
+	if (!shared_fence_count)
+	{
+		struct dma_fence *fence = reservation_object_get_excl(resv);
+
+		if (is_blocking_fence(fence))
+		{
+			if (allocate_blocking_fence_storage(pvr_fence_frame, 1))
+			{	
+				ret = install_and_get_blocking_fence(pvr_fence_frame, 0, fence);
+			}
+			else
+			{
+				dma_fence_put(fence_to_signal);
+				return -ENOMEM;
+			}
+		}
+		else
+		{
+			ret = 1;
+		}
+
+		reservation_object_add_excl_fence(resv, fence_to_signal);
+		return update_reservation_return_value(ret, true);
+	}
+
+	for (i = 0, blocking_fence_count = 0; i < shared_fence_count; i++)
+	{
+
+		struct dma_fence *fence = rcu_dereference_protected(flist->shared[i], reservation_object_held(resv));
+
+		if (is_blocking_fence(fence))
+		{
+			blocking_fence_count++;
+		}
+	}
+
+	ret = 1;
+	if (blocking_fence_count)
+	{
+		if (allocate_blocking_fence_storage(pvr_fence_frame, blocking_fence_count))
+		{
+			unsigned index = 0;
+
+			for (i = 0; i < shared_fence_count; i++)
+			{
+				struct dma_fence *fence = rcu_dereference_protected(flist->shared[i], reservation_object_held(resv));
+
+				if (is_blocking_fence(fence))
+				{
+					if (!install_and_get_blocking_fence(pvr_fence_frame, index++, fence))
+					{
+						ret = 0;
+					}
+				}
+			}
+		}
+		else
+		{
+			dma_fence_put(fence_to_signal);
+			return -ENOMEM;
+		}
+	}
+
+	reservation_object_add_excl_fence(resv, fence_to_signal);
+
+	return update_reservation_return_value(ret, false);
+}
+
+static int update_reservation_object_fences_src(struct pvr_fence_frame *pvr_fence_frame,
+						struct reservation_object *resv)
+{
+	struct dma_fence *fence_to_signal;
+	struct dma_fence *fence;
+	int ret;
+
+	ret = reservation_object_reserve_shared(resv);
+	if (ret)
+	{
+		return ret;
+	}
+
+	fence_to_signal = create_fence_to_signal(pvr_fence_frame);
+	if (!fence_to_signal)
+	{
+		return -ENOMEM;
+	}
+
+	if (!pvr_fence_frame->have_blocking_fences)
+	{
+		reservation_object_add_shared_fence(resv, fence_to_signal);
+
+		return 0;
+	}
+
+	fence = reservation_object_get_excl(resv);
+	if (is_blocking_fence(fence))
+	{
+		if (allocate_blocking_fence_storage(pvr_fence_frame, 1))
+		{	
+			ret = install_and_get_blocking_fence(pvr_fence_frame, 0, fence);
+		}
+		else
+		{
+			dma_fence_put(fence_to_signal);
+			return -ENOMEM;
+		}
+	}
+	else
+	{
+		ret = 1;
+	}
+
+	reservation_object_add_shared_fence(resv, fence_to_signal);
+
+	return update_reservation_return_value(ret, true);
+}
+
+/* Must be called with pvr_fence_context mutex held */
+static void destroy_fence_frame(struct pvr_fence_frame *pvr_fence_frame)
+{
+	unsigned i;
+
+	signal_and_put_fence(pvr_fence_frame);
+
+	for (i = 0; i < pvr_fence_frame->blocking_fence_count; i++)
+	{
+		uninstall_and_put_blocking_fence(pvr_fence_frame, i);
+	}
+	free_blocking_fence_storage(pvr_fence_frame);
+
+	list_del(&pvr_fence_frame->fence_frame_list);
+
+	kfree(pvr_fence_frame);
+}
+
+static inline bool sync_GE(const u32 a, const u32 b)
+{
+	return (a - b) < (U32_MAX / 2);
+}
+static inline bool sync_GT(const u32 a, const u32 b)
+{
+	return (a != b) && sync_GE(a, b);
+}
+
+static bool sync_is_ready(struct pvr_fence_frame *pvr_fence_frame)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = pvr_fence_frame->pvr_fence_context->psSyncInfo;
+
+	return (!pvr_fence_frame->is_dst ||
+			sync_GE(psSyncInfo->psSyncData->ui32ReadOpsComplete,
+					pvr_fence_frame->ui32ReadOpsPending)) &&
+				sync_GE(psSyncInfo->psSyncData->ui32ReadOps2Complete,
+					pvr_fence_frame->ui32ReadOps2Pending) &&
+				sync_GE(psSyncInfo->psSyncData->ui32WriteOpsComplete,
+					pvr_fence_frame->ui32WriteOpsPending);
+}
+
+static bool sync_gpu_read_op_is_complete(struct pvr_fence_frame *pvr_fence_frame)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = pvr_fence_frame->pvr_fence_context->psSyncInfo;
+
+	/*
+	 * If there aren't any blocking fences, we will have recorded the
+	 * read ops pending value after it had been updated for the GPU
+	 * op.
+	 */
+	return pvr_fence_frame->have_blocking_fences ?
+			sync_GT(psSyncInfo->psSyncData->ui32ReadOpsComplete,
+				pvr_fence_frame->ui32ReadOpsPending) : 
+			sync_GE(psSyncInfo->psSyncData->ui32ReadOpsComplete,
+				pvr_fence_frame->ui32ReadOpsPending);
+}
+
+static bool sync_gpu_write_op_is_complete(struct pvr_fence_frame *pvr_fence_frame)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = pvr_fence_frame->pvr_fence_context->psSyncInfo;
+
+	/*
+	 * If there aren't any blocking fences, we will have recorded the
+	 * write ops pending value after it had been updated for the GPU
+	 * op.
+	 */
+	return pvr_fence_frame->have_blocking_fences ?
+			sync_GT(psSyncInfo->psSyncData->ui32WriteOpsComplete,
+				pvr_fence_frame->ui32WriteOpsPending) :
+			sync_GE(psSyncInfo->psSyncData->ui32WriteOpsComplete,
+				pvr_fence_frame->ui32WriteOpsPending);
+}
+
+static void sync_complete_read_op(struct pvr_fence_frame *pvr_fence_frame)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = pvr_fence_frame->pvr_fence_context->psSyncInfo;
+
+	psSyncInfo->psSyncData->ui32ReadOps2Complete = ++pvr_fence_frame->ui32ReadOps2Pending;
+}
+
+static void sync_complete_write_op(struct pvr_fence_frame *pvr_fence_frame)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = pvr_fence_frame->pvr_fence_context->psSyncInfo;
+
+	psSyncInfo->psSyncData->ui32WriteOpsComplete = ++pvr_fence_frame->ui32WriteOpsPending;
+}
+
+static bool fence_work(struct pvr_fence_context *pvr_fence_context)
+{
+	bool schedule_device_callbacks = false;
+
+	for(;;)
+	{
+		struct pvr_fence_frame *pvr_fence_frame;
+		bool reprocess = false;
+		bool next_frame = false;
+
+		pvr_fence_frame = list_first_entry_or_null(&pvr_fence_context->fence_frame_list, struct pvr_fence_frame, fence_frame_list);
+
+		if (pvr_fence_frame)
+		{
+			if (!atomic_read(&pvr_fence_frame->blocking_count) && sync_is_ready(pvr_fence_frame))
+			{
+				switch (pvr_fence_frame->blocked_on)
+				{
+					case BLOCKED_ON_READ:
+						sync_complete_read_op(pvr_fence_frame);
+						pvr_fence_frame->blocked_on = 0;
+						schedule_device_callbacks = true;
+						reprocess = true;
+						break;
+					case BLOCKED_ON_WRITE:
+						sync_complete_write_op(pvr_fence_frame);
+						pvr_fence_frame->blocked_on = 0;
+						schedule_device_callbacks = true;
+						reprocess = true;
+						break;
+					default:
+						next_frame = pvr_fence_frame->is_dst ? sync_gpu_write_op_is_complete(pvr_fence_frame) : sync_gpu_read_op_is_complete(pvr_fence_frame);
+						break;
+				}
+
+				if (pvr_fence_frame->unblock)
+				{
+					next_frame = true;
+				}
+			}
+		}
+
+		if (next_frame)
+		{
+			destroy_fence_frame(pvr_fence_frame);
+		}
+		else
+		{
+			if (!reprocess)
+			{
+				break;
+			}
+		}
+
+	}
+
+	return schedule_device_callbacks;
+}
+
+static void do_fence_work(struct work_struct *work)
+{
+	struct pvr_fence_context *pvr_fence_context = container_of(work, struct pvr_fence_context, fence_work);
+	bool schedule_device_callbacks;
+
+	mutex_lock(&pvr_fence_context->mutex);
+	schedule_device_callbacks = fence_work(pvr_fence_context);
+	mutex_unlock(&pvr_fence_context->mutex);
+
+	if (schedule_device_callbacks)
+	{
+		PVRSRVScheduleDeviceCallbacks();
+	}
+
+}
+
+void PVRLinuxFenceContextDestroy(IMG_HANDLE hFenceContext)
+{
+
+	struct pvr_fence_context *pvr_fence_context = (struct pvr_fence_context *)hFenceContext;
+	struct list_head *entry, *temp;
+
+	mutex_lock(&pvr_fence_mutex);
+	mutex_lock(&pvr_fence_context->mutex);
+
+	list_del(&pvr_fence_context->fence_context_list);
+	if (!list_empty(&pvr_fence_context->fence_context_notify_list))
+	{
+		list_del(&pvr_fence_context->fence_context_notify_list);
+	}
+	mutex_unlock(&pvr_fence_mutex);
+
+	list_for_each_safe(entry, temp, &pvr_fence_context->fence_frame_list)
+	{
+		struct pvr_fence_frame *pvr_fence_frame = list_entry(entry, struct pvr_fence_frame, fence_frame_list);
+ 
+		destroy_fence_frame(pvr_fence_frame);
+	}
+
+	mutex_unlock(&pvr_fence_context->mutex);
+
+	flush_work(&pvr_fence_context->fence_work);
+
+	mutex_destroy(&pvr_fence_context->mutex);
+
+	DmaBufFreeNativeSyncHandle(pvr_fence_context->hNativeSync);
+
+	kfree(pvr_fence_context);
+}
+
+IMG_HANDLE PVRLinuxFenceContextCreate(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_HANDLE hImport)
+{
+	struct pvr_fence_context *pvr_fence_context;
+
+	pvr_fence_context = kzalloc(sizeof(*pvr_fence_context), GFP_KERNEL);
+	if (!pvr_fence_context)
+	{
+		return NULL;
+	}
+
+	pvr_fence_context->hNativeSync = DmaBufGetNativeSyncHandle(hImport);
+	if (!pvr_fence_context->hNativeSync)
+	{
+		kfree(pvr_fence_context);
+		return NULL;
+	}
+
+	INIT_LIST_HEAD(&pvr_fence_context->fence_frame_list);
+	INIT_LIST_HEAD(&pvr_fence_context->fence_context_list);
+	INIT_LIST_HEAD(&pvr_fence_context->fence_context_notify_list);
+
+	mutex_init(&pvr_fence_context->mutex);
+	
+	INIT_WORK(&pvr_fence_context->fence_work, do_fence_work);
+
+	pvr_fence_context->psSyncInfo = psSyncInfo;
+	mutex_lock(&pvr_fence_mutex);
+	list_add_tail(&pvr_fence_context->fence_context_list, &fence_context_list);
+	mutex_unlock(&pvr_fence_mutex);
+
+	return (IMG_HANDLE)pvr_fence_context;
+}
+
+static int process_reservation_object(struct pvr_fence_context *pvr_fence_context, struct reservation_object *resv, bool is_dst, u32 tag, bool have_blocking_fences)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = pvr_fence_context->psSyncInfo;
+	struct pvr_fence_frame *pvr_fence_frame;
+	int ret;
+
+	pvr_fence_frame = kzalloc(sizeof(*pvr_fence_frame), GFP_KERNEL);
+	if (!pvr_fence_frame)
+	{
+		return -ENOMEM;
+	}
+
+	pvr_fence_frame->is_dst = is_dst;
+	pvr_fence_frame->tag = tag;
+	pvr_fence_frame->pvr_fence_context = pvr_fence_context;
+	pvr_fence_frame->have_blocking_fences = have_blocking_fences;
+	atomic_set(&pvr_fence_frame->blocking_count, 0);
+	INIT_LIST_HEAD(&pvr_fence_frame->fence_frame_list);
+
+	ret = is_dst ?
+		update_reservation_object_fences_dst(pvr_fence_frame, resv) :
+		update_reservation_object_fences_src(pvr_fence_frame, resv);
+	if (ret < 0)
+	{
+		kfree(pvr_fence_frame);
+		return ret;
+	}
+	else
+	{
+		BUG_ON(ret && !have_blocking_fences);
+
+		pvr_fence_frame->blocked_on = ret;
+
+
+		/*
+		 * If there are no blocking fences, the ops pending values
+		 * are recorded after being updated for the GPU operation,
+		 * rather than before, so the test for completion of the
+		 * operation is different for the two cases.
+		 */
+		pvr_fence_frame->ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+		pvr_fence_frame->ui32ReadOps2Pending = (pvr_fence_frame->blocked_on == BLOCKED_ON_READ) ? SyncTakeReadOp2(psSyncInfo, SYNC_OP_CLASS_LINUX_FENCE) : psSyncInfo->psSyncData->ui32ReadOps2Pending;
+
+		pvr_fence_frame->ui32WriteOpsPending = (pvr_fence_frame->blocked_on == BLOCKED_ON_WRITE) ? SyncTakeWriteOp(psSyncInfo, SYNC_OP_CLASS_LINUX_FENCE) : psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+		list_add_tail(&pvr_fence_frame->fence_frame_list, &pvr_fence_context->fence_frame_list);
+	}
+
+	return 0;
+}
+
+static int process_syncinfo(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, bool is_dst, u32 tag, bool have_blocking_fences)
+{
+	struct pvr_fence_context *pvr_fence_context = (struct pvr_fence_context *)psSyncInfo->hFenceContext;
+	struct reservation_object *resv;
+	int ret = 0;
+
+	if (!pvr_fence_context)
+	{
+		return 0;
+	}
+
+	mutex_lock(&pvr_fence_context->mutex);
+	if ((resv = DmaBufGetReservationObject(pvr_fence_context->hNativeSync)))
+	{
+		ret = process_reservation_object(pvr_fence_context,
+							resv,
+							is_dst,
+							tag,
+							have_blocking_fences);
+	}
+	mutex_unlock(&pvr_fence_context->mutex);
+
+	mutex_lock(&pvr_fence_mutex);
+	mutex_lock(&pvr_fence_context->mutex);
+	if (list_empty(&pvr_fence_context->fence_context_notify_list))
+	{
+		list_add_tail(&pvr_fence_context->fence_context_notify_list, &fence_context_notify_list);
+		queue_work(workqueue, &pvr_fence_context->fence_work);
+	}
+	mutex_unlock(&pvr_fence_context->mutex);
+	mutex_unlock(&pvr_fence_mutex);
+
+	return ret;
+}
+
+
+static inline bool sync_enabled(const IMG_BOOL *pbEnabled,
+				const IMG_HANDLE *phSyncInfo,
+				unsigned index)
+{
+	return (!pbEnabled || pbEnabled[index]) && phSyncInfo && phSyncInfo[index];
+}
+
+static bool resv_is_blocking(struct reservation_object *resv, bool is_dst)
+{
+	struct reservation_object_list *flist;
+	struct dma_fence *fence;
+	bool blocking;
+	unsigned shared_count;
+	unsigned seq;
+
+retry:
+	shared_count = 0;
+	blocking = false;
+
+	seq = read_seqcount_begin(&resv->seq);
+	rcu_read_lock();
+
+	flist = rcu_dereference(resv->fence);
+	if (read_seqcount_retry(&resv->seq, seq))
+	{
+		goto unlock_retry;
+	}
+
+	if (flist)
+	{
+		shared_count = flist->shared_count;
+	}
+
+	if (is_dst)
+	{
+		unsigned i;
+
+		for (i = 0; (i < shared_count) && !blocking; i++)
+		{
+			fence = rcu_dereference(flist->shared[i]);
+
+			blocking = is_unsignalled_blocking_fence(fence);
+		}
+	}
+
+	if (!blocking && (!is_dst || !shared_count))
+	{
+		fence = rcu_dereference(resv->fence_excl);
+		if (read_seqcount_retry(&resv->seq, seq))
+		{
+			goto unlock_retry;
+		}
+
+		blocking = is_unsignalled_blocking_fence(fence);
+	}
+
+	rcu_read_unlock();
+
+	return blocking;
+
+unlock_retry:
+	rcu_read_unlock();
+	goto retry;
+}
+
+static unsigned count_reservation_objects(unsigned num_syncs,
+					IMG_HANDLE *phSyncInfo,
+					const IMG_BOOL *pbEnabled,
+					bool is_dst,
+					bool *have_blocking_fences)
+{
+	unsigned i;
+	unsigned count = 0;
+	bool blocking_fences = false;
+
+	for (i = 0; i < num_syncs; i++)
+	{
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+		struct pvr_fence_context *pvr_fence_context;
+
+		if (!sync_enabled(pbEnabled, phSyncInfo, i))
+		{
+			continue;
+		}
+
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)phSyncInfo[i];
+		pvr_fence_context = (struct pvr_fence_context *)psSyncInfo->hFenceContext;
+		if (pvr_fence_context)
+		{
+			struct reservation_object *resv;
+
+			if ((resv = DmaBufGetReservationObject(pvr_fence_context->hNativeSync)))
+			{
+				count++;
+
+				if (!blocking_fences)
+				{
+					blocking_fences = resv_is_blocking(resv,
+								is_dst);
+				}
+			}
+		}
+	}
+
+	*have_blocking_fences = blocking_fences;
+	return count;
+}
+
+static unsigned get_reservation_objects(unsigned num_resvs,
+					struct reservation_object **resvs,
+					unsigned num_syncs,
+					IMG_HANDLE *phSyncInfo,
+					const IMG_BOOL *pbEnabled)
+{
+	unsigned i;
+	unsigned count = 0;
+
+	for (i = 0; i < num_syncs; i++)
+	{
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+		struct pvr_fence_context *pvr_fence_context;
+		
+		if (!sync_enabled(pbEnabled, phSyncInfo, i))
+		{
+			continue;
+		}
+
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)phSyncInfo[i];
+		pvr_fence_context = (struct pvr_fence_context *)psSyncInfo->hFenceContext;
+		if (pvr_fence_context)
+		{
+			struct reservation_object *resv;
+
+			if ((resv = DmaBufGetReservationObject(pvr_fence_context->hNativeSync)))
+			{
+				BUG_ON(count >= num_resvs);
+				resvs[count++] = resv;
+			}
+		}
+	}
+
+	return count;
+}
+
+static void get_all_reservation_objects(unsigned num_resvs,
+					struct reservation_object **resvs,
+					IMG_UINT32 ui32NumSrcSyncs,
+					IMG_HANDLE *phSrcSyncInfo,
+					const IMG_BOOL *pbSrcEnabled,
+					IMG_UINT32 ui32NumDstSyncs,
+					IMG_HANDLE *phDstSyncInfo,
+					const IMG_BOOL *pbDstEnabled)
+{
+	unsigned num_src_resvs;
+
+	num_src_resvs = get_reservation_objects(num_resvs,
+						resvs,
+						ui32NumSrcSyncs,
+						phSrcSyncInfo,
+						pbSrcEnabled);
+
+	get_reservation_objects(num_resvs - num_src_resvs, 
+					&resvs[num_src_resvs],
+					ui32NumDstSyncs,
+					phDstSyncInfo,
+					pbDstEnabled);
+}
+
+static void unlock_reservation_objects(unsigned num_resvs,
+					struct reservation_object **resvs)
+{
+	unsigned i;
+
+	for (i = 0; i < num_resvs; i++)
+	{
+		if (resvs[i])
+		{
+			ww_mutex_unlock(&(resvs[i]->lock));
+		}
+	}
+}
+
+static int lock_reservation_objects_no_retry(struct ww_acquire_ctx *ww_acquire_ctx,
+						bool interruptible,
+						unsigned num_resvs,
+						struct reservation_object **resvs,
+						struct reservation_object **contended_resv)
+{
+	unsigned i;
+
+	for (i = 0; i < num_resvs; i++)
+	{
+		int ret;
+
+		if (!resvs[i])
+		{
+			continue;
+		}
+		if (resvs[i] == *contended_resv)
+		{
+			*contended_resv = NULL;
+			continue;
+		}
+
+		ret = interruptible ?
+			ww_mutex_lock_interruptible(&(resvs[i]->lock), ww_acquire_ctx) :
+			ww_mutex_lock(&(resvs[i]->lock), ww_acquire_ctx);
+		if (ret)
+		{
+			if (ret == -EALREADY)
+			{
+				resvs[i] = NULL;
+				continue;
+			}
+
+			unlock_reservation_objects(i, resvs);
+
+			if (*contended_resv)
+			{
+				ww_mutex_unlock(&((*contended_resv)->lock));
+				*contended_resv = NULL;
+			}
+
+			if (ret == -EDEADLK)
+			{
+				*contended_resv = resvs[i];
+			}
+
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int lock_reservation_objects(struct ww_acquire_ctx *ww_acquire_ctx,
+					bool interruptible,
+					unsigned num_resvs,
+					struct reservation_object **resvs)
+{
+	int ret;
+	struct reservation_object *contended_resv = NULL;
+
+	do {
+		ret = lock_reservation_objects_no_retry(ww_acquire_ctx,
+							interruptible,
+							num_resvs,
+							resvs,
+							&contended_resv);
+		if (ret == -EDEADLK)
+		{
+			if (interruptible)
+			{
+				int res = ww_mutex_lock_slow_interruptible(
+						&(contended_resv->lock),
+						ww_acquire_ctx);
+				if (res)
+				{
+					return res;
+				}
+			}
+			else
+			{
+				ww_mutex_lock_slow(&(contended_resv->lock), ww_acquire_ctx);
+			}
+		}
+	} while (ret == -EDEADLK);
+
+	return ret;
+}
+
+static int process_syncinfos(u32 tag,
+				bool is_dst,
+				bool have_blocking_fences,
+				IMG_UINT32 ui32NumSyncs,
+				IMG_HANDLE *phSyncInfo,
+				const IMG_BOOL *pbEnabled)
+{
+	unsigned i;
+
+	for (i = 0; i < ui32NumSyncs; i++)
+	{
+		if (sync_enabled(pbEnabled, phSyncInfo, i))
+		{
+			PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)phSyncInfo[i];
+			int ret;
+				
+			ret = process_syncinfo(psSyncInfo,
+						is_dst,
+						tag,
+						have_blocking_fences);
+			if (ret)
+			{
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int process_all_syncinfos(u32 tag,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled,
+				bool have_blocking_fences)
+{
+	int ret;
+
+	ret = process_syncinfos(tag,
+				false,
+				have_blocking_fences,
+				ui32NumSrcSyncs,
+				phSrcSyncInfo,
+				pbSrcEnabled);
+
+	if (ret)
+	{
+		return ret;
+	}
+
+	ret = process_syncinfos(tag,
+				true,
+				have_blocking_fences,
+				ui32NumDstSyncs,
+				phDstSyncInfo,
+				pbDstEnabled);
+
+	return ret;
+}
+
+static void unblock_frames(u32 tag,
+				IMG_UINT32 ui32NumSyncs,
+				IMG_HANDLE *phSyncInfo,
+				const IMG_BOOL *pbEnabled)
+{
+	unsigned i;
+
+	for (i = 0; i < ui32NumSyncs; i++)
+	{
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+		struct pvr_fence_context *pvr_fence_context;
+		struct list_head *entry;
+
+		if (!sync_enabled(pbEnabled, phSyncInfo, i))
+		{
+			continue;
+		}
+
+		psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)phSyncInfo[i];
+		pvr_fence_context = (struct pvr_fence_context *)psSyncInfo->hFenceContext;
+		if (!pvr_fence_context)
+		{
+			continue;
+		}
+
+
+		mutex_lock(&pvr_fence_context->mutex);
+
+		list_for_each(entry, &pvr_fence_context->fence_frame_list)
+		{
+			struct pvr_fence_frame *pvr_fence_frame = list_entry(entry, struct pvr_fence_frame, fence_frame_list);
+ 
+			if (pvr_fence_frame->tag == tag)
+			{
+				pvr_fence_frame->unblock = true;
+			}
+		}
+
+		mutex_unlock(&pvr_fence_context->mutex);
+	}
+
+	return;
+}
+
+static void unblock_all_frames(u32 tag,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled)
+{
+	unblock_frames(tag,
+			ui32NumSrcSyncs,
+			phSrcSyncInfo,
+			pbSrcEnabled);
+
+	unblock_frames(tag,
+			ui32NumDstSyncs,
+			phDstSyncInfo,
+			pbDstEnabled);
+}
+
+static PVRSRV_ERROR pvr_error(int error)
+{
+	switch(error)
+	{
+		case 0:
+			return PVRSRV_OK;
+		case -EINTR:
+			return PVRSRV_ERROR_RETRY;
+		case -ENOMEM:
+			return PVRSRV_ERROR_OUT_OF_MEMORY;
+		default:
+			break;
+	}
+
+	return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static u32 new_frame_tag(void)
+{
+	static u32 frame_tag;
+
+	return (++frame_tag) ? frame_tag : ++frame_tag;
+}
+
+IMG_UINT32 PVRLinuxFenceNumResvObjs(IMG_BOOL *pbBlockingFences,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled)
+{
+	unsigned count;
+	bool blocking_fences_src, blocking_fences_dst;
+
+	count = count_reservation_objects(ui32NumSrcSyncs,
+					phSrcSyncInfo,
+					pbSrcEnabled,
+					false,
+					&blocking_fences_src);
+
+	count += count_reservation_objects(ui32NumDstSyncs,
+						phDstSyncInfo,
+						pbDstEnabled,
+						true,
+						&blocking_fences_dst);
+
+	*pbBlockingFences = (IMG_BOOL) (blocking_fences_src |
+						blocking_fences_dst);
+
+	return count;
+}
+
+PVRSRV_ERROR PVRLinuxFenceProcess(IMG_UINT32 *pui32Tag,
+				IMG_UINT32 ui32NumResvObjs,
+				IMG_BOOL bBlockingFences,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled)
+{
+	u32 tag;
+	struct ww_acquire_ctx ww_acquire_ctx;
+	struct reservation_object **resvs = NULL;
+	int ret;
+
+	if (!ui32NumResvObjs)
+	{
+		*pui32Tag = 0;
+		ret = 0;
+		goto exit;
+	}
+	tag = new_frame_tag();
+
+	resvs = kmalloc(ui32NumResvObjs * sizeof(*resvs), GFP_KERNEL);
+	if (!resvs)
+	{
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	get_all_reservation_objects(ui32NumResvObjs,
+					resvs,
+					ui32NumSrcSyncs,
+					phSrcSyncInfo,
+					pbSrcEnabled,
+					ui32NumDstSyncs,
+					phDstSyncInfo,
+					pbDstEnabled);
+
+	ww_acquire_init(&ww_acquire_ctx, &reservation_ww_class);
+
+	/*
+	 * If there are no blocking fences, we will be processing
+	 * reservation objects after the GPU operation has been
+	 * started, so returning an error that may result in the
+	 * GPU operation being retried may be inappropriate.
+	 */
+	ret = lock_reservation_objects(&ww_acquire_ctx,
+				       (bool)bBlockingFences,
+				       ui32NumResvObjs,
+				       resvs);
+	if (ret)
+	{
+		ww_acquire_fini(&ww_acquire_ctx);
+		goto exit;
+	}
+	ww_acquire_done(&ww_acquire_ctx);
+
+	ret = process_all_syncinfos(tag,
+					ui32NumSrcSyncs,
+					phSrcSyncInfo,
+					pbSrcEnabled,
+					ui32NumDstSyncs,
+					phDstSyncInfo,
+					pbDstEnabled,
+					(bool)bBlockingFences);
+
+	unlock_reservation_objects(ui32NumResvObjs, resvs);
+
+	ww_acquire_fini(&ww_acquire_ctx);
+
+	if (ret)
+	{
+		unblock_all_frames(tag,
+					ui32NumSrcSyncs,
+					phSrcSyncInfo,
+					pbSrcEnabled,
+					ui32NumDstSyncs,
+					phDstSyncInfo,
+					pbDstEnabled);
+	}
+	else
+	{
+		*pui32Tag = tag;
+	}
+
+exit:
+	if (resvs)
+	{
+		kfree(resvs);
+	}
+	return pvr_error(ret);
+
+}
+
+void PVRLinuxFenceRelease(IMG_UINT32 uTag,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled)
+{
+	if (uTag)
+	{
+		unblock_all_frames(uTag,
+				ui32NumSrcSyncs,
+				phSrcSyncInfo,
+				pbSrcEnabled,
+				ui32NumDstSyncs,
+				phDstSyncInfo,
+				pbDstEnabled);
+	}
+}
+
+void PVRLinuxFenceCheckAll(void)
+{
+	struct list_head *entry, *temp;
+	bool schedule_device_callbacks = false;
+
+	mutex_lock(&pvr_fence_mutex);
+	list_for_each_safe(entry, temp, &fence_context_notify_list)
+	{
+		struct pvr_fence_context *pvr_fence_context = list_entry(entry, struct pvr_fence_context, fence_context_notify_list);
+
+		mutex_lock(&pvr_fence_context->mutex);
+		if (list_empty(&pvr_fence_context->fence_frame_list))
+		{
+			list_del_init(&pvr_fence_context->fence_context_notify_list);
+		}
+		else
+		{
+			if (fence_work(pvr_fence_context))
+			{
+				schedule_device_callbacks = true;
+			}
+		}
+		mutex_unlock(&pvr_fence_context->mutex);
+	}
+	mutex_unlock(&pvr_fence_mutex);
+
+	if (schedule_device_callbacks)
+		PVRSRVScheduleDeviceCallbacks();
+}
+
+void PVRLinuxFenceDeInit(void)
+{
+	unsigned fences_remaining;
+	bool contexts_leaked;
+
+	if (workqueue)
+	{
+		destroy_workqueue(workqueue);
+	}
+
+	fences_remaining = atomic_read(&fences_outstanding);
+	if (fences_remaining)
+	{
+		printk(KERN_WARNING "%s: %u fences leaked\n",
+				__func__, fences_remaining);
+	}
+
+#if defined(DEBUG)
+	printk(KERN_INFO "%s: %u fences allocated\n",
+			__func__, atomic_read(&fences_allocated));
+
+	printk(KERN_INFO "%s: %u fences signalled\n",
+			__func__, atomic_read(&fences_signalled));
+
+	printk(KERN_INFO "%s: %u callbacks installed\n",
+			__func__, atomic_read(&callbacks_installed));
+
+	printk(KERN_INFO "%s: %u callbacks called\n",
+			__func__, atomic_read(&callbacks_called));
+#endif
+
+	mutex_lock(&pvr_fence_mutex);
+	contexts_leaked = !list_empty(&fence_context_list);
+	mutex_unlock(&pvr_fence_mutex);
+
+	mutex_destroy(&pvr_fence_mutex);
+
+	BUG_ON(contexts_leaked);
+}
+
+int PVRLinuxFenceInit(void)
+{
+	workqueue = create_workqueue("PVR Linux Fence");
+	if (!workqueue)
+	{
+		return -ENOMEM;
+	}
+
+	fence_context = dma_fence_context_alloc(1);
+
+	return 0;
+}
+#else	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17)) */
+IMG_HANDLE PVRLinuxFenceContextCreate(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_HANDLE hImport)
+{
+	(void) psSyncInfo;
+	(void) hImport;
+
+	return (IMG_HANDLE)(IMG_UINTPTR_T)0xbad;
+}
+
+void PVRLinuxFenceContextDestroy(IMG_HANDLE hFenceContext)
+{
+	(void) hFenceContext;
+}
+
+IMG_UINT32 PVRLinuxFenceNumResvObjs(IMG_BOOL *pbBlockingFences,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled)
+{
+	(void) pbBlockingFences;
+	(void) ui32NumSrcSyncs;
+	(void) phSrcSyncInfo;
+	(void) pbSrcEnabled;
+	(void) ui32NumDstSyncs;
+	(void) phDstSyncInfo;
+	(void) pbDstEnabled;
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRLinuxFenceProcess(IMG_UINT32 *pui32Tag,
+				IMG_UINT32 ui32NumResvObjs,
+				IMG_BOOL bBlockingFences,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled)
+{
+	(void) pui32Tag;
+	(void) ui32NumResvObjs;
+	(void) bBlockingFences;
+	(void) ui32NumSrcSyncs;
+	(void) phSrcSyncInfo;
+	(void) pbSrcEnabled;
+	(void) ui32NumDstSyncs;
+	(void) phDstSyncInfo;
+	(void) pbDstEnabled;
+
+	return PVRSRV_OK;
+}
+
+void PVRLinuxFenceRelease(IMG_UINT32 ui32Tag,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled)
+{
+	(void) ui32Tag;
+	(void) ui32NumSrcSyncs;
+	(void) phSrcSyncInfo;
+	(void) pbSrcEnabled;
+	(void) ui32NumDstSyncs;
+	(void) phDstSyncInfo;
+	(void) pbDstEnabled;
+}
+
+void PVRLinuxFenceCheckAll(void)
+{
+}
+
+int PVRLinuxFenceInit(void)
+{
+	return 0;
+}
+
+void PVRLinuxFenceDeInit(void)
+{
+}
+#endif	/* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17)) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_linux_fence.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_linux_fence.h
new file mode 100644
index 0000000..aed12ff
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_linux_fence.h
@@ -0,0 +1,81 @@
+/*************************************************************************/ /*!
+@File
+@Title          PowerVR Linux fence interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    drm module
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__PVR_LINUX_FENCE_H__)
+#define __PVR_LINUX_FENCE_H__
+
+IMG_HANDLE PVRLinuxFenceContextCreate(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_HANDLE hImport);
+void PVRLinuxFenceContextDestroy(IMG_HANDLE hFenceContext);
+
+IMG_UINT32 PVRLinuxFenceNumResvObjs(IMG_BOOL *pbBlockingFences,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled);
+
+PVRSRV_ERROR PVRLinuxFenceProcess(IMG_UINT32 *pui32Tag,
+				IMG_UINT32 ui32NumResvObjs,
+				IMG_BOOL bBlockingFences,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled);
+
+void PVRLinuxFenceRelease(IMG_UINT32 ui32Tag,
+				IMG_UINT32 ui32NumSrcSyncs,
+				IMG_HANDLE *phSrcSyncInfo,
+				const IMG_BOOL *pbSrcEnabled,
+				IMG_UINT32 ui32NumDstSyncs,
+				IMG_HANDLE *phDstSyncInfo,
+				const IMG_BOOL *pbDstEnabled);
+
+void PVRLinuxFenceCheckAll(void);
+
+int PVRLinuxFenceInit(void);
+void PVRLinuxFenceDeInit(void);
+
+#endif /* !defined(__PVR_LINUX_FENCE_H__) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c
new file mode 100644
index 0000000..7c3006d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.c
@@ -0,0 +1,141 @@
+/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* vi: set ts=8 sw=8 sts=8: */
+/*************************************************************************/ /*!
+@File
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/spinlock_types.h>
+#include <linux/atomic.h>
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/bug.h>
+#include <linux/sync_file.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "servicesext.h"
+#include "pvr_sw_fence.h"
+
+struct PVR_SW_FENCE_CONTEXT
+{
+	struct kref sRef;
+	IMG_INT32 i32ContextId;
+	const char *psCtxName;
+	const char *psDriverName;
+	atomic_t sSeqno;
+	atomic_t sFenceCnt;
+};
+
+struct PVR_SW_FENCE
+{
+	struct dma_fence sBase;
+	struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx;
+	spinlock_t sLock;
+};
+
+#define to_pvr_sw_fence(fence) container_of(fence, struct PVR_SW_FENCE, sBase)
+
+static inline unsigned
+pvr_sw_fence_context_seqno_next(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx)
+{
+	return atomic_inc_return(&psSWFenceCtx->sSeqno) - 1;
+}
+
+static const char * pvr_sw_fence_get_driver_name(struct dma_fence *psFence)
+{
+	struct PVR_SW_FENCE *psPVRSwFence = to_pvr_sw_fence(psFence);
+
+	return psPVRSwFence->psSWFenceCtx->psDriverName;
+}
+
+static const char * pvr_sw_fence_get_timeline_name(struct dma_fence *psFence)
+{
+	struct PVR_SW_FENCE *psPVRSwFence = to_pvr_sw_fence(psFence);
+
+	return psPVRSwFence->psSWFenceCtx->psCtxName;
+}
+
+static bool pvr_sw_fence_enable_signaling(struct dma_fence *psFence)
+{
+	return true;
+}
+
+static void pvr_sw_fence_context_destroy_kref(struct kref *kref)
+{
+	struct PVR_SW_FENCE_CONTEXT *psPVRSwFence = container_of(kref, struct PVR_SW_FENCE_CONTEXT, sRef);
+	unsigned fence_count;
+
+	fence_count = atomic_read(&psPVRSwFence->sFenceCnt);
+	if (WARN_ON(fence_count))
+		pr_debug("%s context has %u fence(s) remaining\n", psPVRSwFence->psCtxName, fence_count);
+
+	kfree(psPVRSwFence);
+}
+
+static void pvr_sw_fence_release(struct dma_fence *psFence)
+{
+	struct PVR_SW_FENCE *psPVRSwFence = to_pvr_sw_fence(psFence);
+
+	atomic_dec(&psPVRSwFence->psSWFenceCtx->sFenceCnt);
+	kref_put(&psPVRSwFence->psSWFenceCtx->sRef,
+		pvr_sw_fence_context_destroy_kref);
+	kfree(psPVRSwFence);
+}
+
+static struct dma_fence_ops pvr_sw_fence_ops = {
+	.get_driver_name = pvr_sw_fence_get_driver_name,
+	.get_timeline_name = pvr_sw_fence_get_timeline_name,
+	.enable_signaling = pvr_sw_fence_enable_signaling,
+	.wait = dma_fence_default_wait,
+	.release = pvr_sw_fence_release,
+};
+
+struct PVR_SW_FENCE_CONTEXT *
+pvr_sw_fence_context_create(const char *context_name, const char *driver_name)
+{
+	struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx;
+
+	psSWFenceCtx = kmalloc(sizeof(*psSWFenceCtx), GFP_KERNEL);
+	if (!psSWFenceCtx)
+		return NULL;
+
+	psSWFenceCtx->i32ContextId = dma_fence_context_alloc(1);
+	psSWFenceCtx->psCtxName = context_name;
+	psSWFenceCtx->psDriverName = driver_name;
+	atomic_set(&psSWFenceCtx->sSeqno, 0);
+	atomic_set(&psSWFenceCtx->sFenceCnt, 0);
+	kref_init(&psSWFenceCtx->sRef);
+
+	return psSWFenceCtx;
+}
+
+void pvr_sw_fence_context_destroy(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx)
+{
+	kref_put(&psSWFenceCtx->sRef, pvr_sw_fence_context_destroy_kref);
+}
+
+struct dma_fence *
+pvr_sw_fence_create(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx)
+{
+	struct PVR_SW_FENCE *psPVRSwFence;
+	unsigned int seqno;
+
+	psPVRSwFence = kmalloc(sizeof(*psPVRSwFence), GFP_KERNEL);
+	if (!psPVRSwFence)
+		return NULL;
+
+	spin_lock_init(&psPVRSwFence->sLock);
+	psPVRSwFence->psSWFenceCtx = psSWFenceCtx;
+
+	seqno = pvr_sw_fence_context_seqno_next(psSWFenceCtx);
+	dma_fence_init(&psPVRSwFence->sBase, &pvr_sw_fence_ops, &psPVRSwFence->sLock, psSWFenceCtx->i32ContextId, seqno);
+
+	atomic_inc(&psSWFenceCtx->sFenceCnt);
+	kref_get(&psSWFenceCtx->sRef);
+
+	return &psPVRSwFence->sBase;
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.h
new file mode 100644
index 0000000..35934ce
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sw_fence.h
@@ -0,0 +1,17 @@
+/*************************************************************************/ /*!
+@File
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#if !defined(__PVR_SW_FENCES_H__)
+#define __PVR_SW_FENCES_H__
+
+struct PVR_SW_FENCE_CONTEXT;
+
+struct PVR_SW_FENCE_CONTEXT *pvr_sw_fence_context_create(const char *name, const char *driver_name);
+void pvr_sw_fence_context_destroy(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx);
+struct dma_fence *pvr_sw_fence_create(struct PVR_SW_FENCE_CONTEXT *psSWFenceCtx);
+
+#endif /* !defined(__PVR_SW_FENCES_H__) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.c
new file mode 100644
index 0000000..56f5949
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.c
@@ -0,0 +1,1492 @@
+/*************************************************************************/ /*!
+@File           pvr_sync.c
+@Title          Kernel driver for Android's sync mechanism
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "pvr_sync_common.h"
+#include "pvr_sync.h"
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/anon_inodes.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+#include "mutex.h"
+#include "lock.h"
+
+//#define DEBUG_PRINT
+
+#if defined(DEBUG_PRINT)
+#define DPF(fmt, ...) PVR_DPF((PVR_DBG_BUFFERED, fmt, __VA_ARGS__))
+#else
+#define DPF(fmt, ...) do {} while(0)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0))
+
+static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
+{
+		return pt->parent;
+}
+
+#define for_each_sync_pt(s, f, c) \
+		(void)c; \
+list_for_each_entry((s), &(f)->pt_list_head, pt_list)
+
+#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+
+#define for_each_sync_pt(s, f, c) \
+		for ((c) = 0, (s) = (struct sync_pt *)(f)->cbs[0].sync_pt; \
+						(c) < (f)->num_fences; \
+						(c)++,   (s) = (struct sync_pt *)(f)->cbs[c].sync_pt)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+
+/* We can't support this code when the MISR runs in atomic context because
+ * PVRSyncFreeSync() may be called by sync_timeline_signal() which may be
+ * scheduled by the MISR. PVRSyncFreeSync() needs to protect the handle
+ * tables against modification and so uses the Linux bridge mutex.
+ *
+ * You can't lock a mutex in atomic context.
+ */
+#if !defined(PVR_LINUX_MISR_USING_WORKQUEUE) && \
+    !defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#error The Android sync driver requires that the SGX MISR runs in wq context
+#endif
+
+/* Multi-purpose workqueue. Various functions in the Google sync driver
+ * may call down to us in atomic context. However, sometimes we may need
+ * to lock a mutex. To work around this conflict, use the workqueue to
+ * defer whatever the operation was.
+ */
+static struct workqueue_struct *gpsWorkQueue;
+
+/* Linux work struct for workqueue. */
+static struct work_struct gsWork;
+
+/* List of timelines, used by MISR callback to find signalled sync points
+ * and also to kick the hardware if signalling may allow progress to be
+ * made.
+ */
+static LIST_HEAD(gTimelineList);
+static DEFINE_MUTEX(gTimelineListLock);
+
+/* The "defer-free" object list. Driver global. */
+static LIST_HEAD(gSyncInfoFreeList);
+static DEFINE_SPINLOCK(gSyncInfoFreeListLock);
+
+/* The "defer-put" object list. Driver global. */
+static LIST_HEAD(gFencePutList);
+static DEFINE_SPINLOCK(gFencePutListLock);
+
+/* Sync point stamp counter -- incremented on creation of a new sync point */
+static IMG_UINT64 gui64SyncPointStamp;
+
+/* Forward declare due to cyclic dependency on gsSyncFenceAllocFOps */
+struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd);
+
+/* Global data relating to PVR services connection */
+
+static struct
+{
+	/* Process that initialized the sync driver. House-keep this so
+	 * the correct per-proc data is used during shutdown. This PID is
+	 * conventionally whatever `pvrsrvctl' was when it was alive.
+	 */
+	IMG_UINT32	ui32Pid;
+
+	/* Device cookie for services allocation functions. The device would
+	 * ordinarily be SGX, and the first/only device in the system.
+	 */
+	IMG_HANDLE	hDevCookie;
+
+	/* Device memory context that all SYNC_INFOs allocated by this driver
+	 * will be created in. Because SYNC_INFOs are placed in a shared heap,
+	 * it does not matter from which process the create ioctl originates.
+	 */
+	IMG_HANDLE	hDevMemContext;
+}
+gsSyncServicesConnection;
+
+/* NOTE: Must only be called with services bridge mutex held */
+static void PVRSyncSWTakeOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+	psKernelSyncInfo->psSyncData->ui32WriteOpsPending = 1;
+}
+
+static void PVRSyncSWCompleteOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+	psKernelSyncInfo->psSyncData->ui32WriteOpsComplete = 1;
+}
+
+static struct PVR_SYNC *
+PVRSyncCreateSync(struct PVR_SYNC_TIMELINE *obj, 
+				  struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo)
+{
+	struct PVR_SYNC *psPt = NULL;
+
+	psPt = (struct PVR_SYNC *)
+		sync_pt_create(&obj->obj, sizeof(struct PVR_SYNC));
+	if(!psPt)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: sync_pt_create failed", __func__));
+		goto err_out;
+	}
+
+	psPt->psSyncData = kmalloc(sizeof(struct PVR_SYNC_DATA), GFP_KERNEL);
+	if(!psPt->psSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_SYNC_DATA",
+				 __func__));
+		goto err_free_pt;
+	}
+
+	atomic_set(&psPt->psSyncData->sRefcount, 1);
+
+	psPt->psSyncData->ui32WOPSnapshot =
+		obj->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending;
+
+	psPt->psSyncData->psSyncInfo = psSyncInfo;
+
+	/* Stamp the point and update the global counter under lock */
+	mutex_lock(&obj->sTimelineLock);
+	psPt->psSyncData->ui64Stamp = gui64SyncPointStamp++;
+	mutex_unlock(&obj->sTimelineLock);
+
+err_out:
+	return psPt;
+err_free_pt:
+	sync_pt_free((struct sync_pt *)psPt);
+	psPt = NULL;	
+	goto err_out;
+}
+
+static IMG_BOOL PVRSyncIsSyncInfoInUse(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo)
+{
+	return !(psSyncInfo->psSyncData->ui32WriteOpsPending ==
+			 psSyncInfo->psSyncData->ui32WriteOpsComplete &&
+			 psSyncInfo->psSyncData->ui32ReadOpsPending ==
+			 psSyncInfo->psSyncData->ui32ReadOpsComplete &&
+			 psSyncInfo->psSyncData->ui32ReadOps2Pending ==
+			 psSyncInfo->psSyncData->ui32ReadOps2Complete);
+}
+
+/* Releases a sync info by adding it to a deferred list to be freed later. */
+static void
+PVRSyncReleaseSyncInfo(struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gSyncInfoFreeListLock, flags);
+	list_add_tail(&psSyncInfo->sHead, &gSyncInfoFreeList);
+	spin_unlock_irqrestore(&gSyncInfoFreeListLock, flags);
+
+	queue_work(gpsWorkQueue, &gsWork);
+}
+
+static void PVRSyncFreeSyncData(struct PVR_SYNC_DATA *psSyncData)
+{
+	PVR_ASSERT(atomic_read(&psSyncData->sRefcount) == 0);
+	PVRSyncReleaseSyncInfo(psSyncData->psSyncInfo);
+	psSyncData->psSyncInfo = NULL;
+	kfree(psSyncData);
+}
+
+static void PVRSyncFreeSync(struct sync_pt *psPt)
+{
+	struct PVR_SYNC *psSync = (struct PVR_SYNC *)psPt;
+#if defined(DEBUG_PRINT)
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+		psSync->psSyncData->psSyncInfo->psBase;
+#endif
+
+	PVR_ASSERT(atomic_read(&psSync->psSyncData->sRefcount) > 0);
+
+	/* Only free on the last reference */
+	if (atomic_dec_return(&psSync->psSyncData->sRefcount) != 0)
+		return;
+
+	DPF("R( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X "
+		"WOP/C=0x%x/0x%x ROP/C=0x%x/0x%x RO2P/C=0x%x/0x%x "
+		"ID=%llu, S=0x%x, F=%p",
+		psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+		psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+		psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr,
+		psSyncInfo->psSyncData->ui32WriteOpsPending,
+		psSyncInfo->psSyncData->ui32WriteOpsComplete,
+		psSyncInfo->psSyncData->ui32ReadOpsPending,
+		psSyncInfo->psSyncData->ui32ReadOpsComplete,
+		psSyncInfo->psSyncData->ui32ReadOps2Pending,
+		psSyncInfo->psSyncData->ui32ReadOps2Complete,
+		psSync->psSyncData->ui64Stamp,
+		psSync->psSyncData->ui32WOPSnapshot,
+		psSync->pt.fence);
+
+	PVRSyncFreeSyncData(psSync->psSyncData);
+	psSync->psSyncData = NULL;
+}
+
+static struct sync_pt *PVRSyncDup(struct sync_pt *sync_pt)
+{
+	struct PVR_SYNC *psPt, *psParentPt = (struct PVR_SYNC *)sync_pt;
+
+	psPt = (struct PVR_SYNC *)
+		sync_pt_create(sync_pt_parent(sync_pt), sizeof(struct PVR_SYNC));
+	if(!psPt)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: sync_pt_create failed", __func__));
+		goto err_out;
+	}
+
+	psPt->psSyncData = psParentPt->psSyncData;
+	atomic_inc(&psPt->psSyncData->sRefcount);
+
+	PVR_ASSERT(atomic_read(&psPt->psSyncData->sRefcount) > 1);
+
+err_out:
+	return (struct sync_pt*)psPt;
+}
+
+static int PVRSyncHasSignaled(struct sync_pt *sync_pt)
+{
+	struct PVR_SYNC *psPt = (struct PVR_SYNC *)sync_pt;
+	struct PVR_SYNC_TIMELINE *psTimeline =
+		(struct PVR_SYNC_TIMELINE *) sync_pt_parent(sync_pt);
+	PVRSRV_SYNC_DATA *psSyncData =
+		psPt->psSyncData->psSyncInfo->psBase->psSyncData;
+
+	if (psSyncData->ui32WriteOpsComplete >= psSyncData->ui32WriteOpsPending)
+	{
+		psTimeline->bSyncHasSignaled = IMG_TRUE;
+		return 1;
+	}
+
+	return 0;
+}
+
+static int PVRSyncCompare(struct sync_pt *a, struct sync_pt *b)
+{
+	IMG_UINT64 ui64StampA = ((struct PVR_SYNC *)a)->psSyncData->ui64Stamp;
+	IMG_UINT64 ui64StampB = ((struct PVR_SYNC *)b)->psSyncData->ui64Stamp;
+
+	if (ui64StampA == ui64StampB)
+		return 0;
+	else if (ui64StampA > ui64StampB)
+		return 1;
+	else
+		return -1;
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0))
+static void PVRSyncPrintTimeline(struct seq_file *s,
+								 struct sync_timeline *psObj)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline = (struct PVR_SYNC_TIMELINE *)psObj;
+
+	seq_printf(s, "WOP/WOC=0x%x/0x%x",
+	           psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+	           psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete);
+}
+
+static void PVRSyncPrint(struct seq_file *s, struct sync_pt *psPt)
+{
+	struct PVR_SYNC *psSync = (struct PVR_SYNC *)psPt;
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+		psSync->psSyncData->psSyncInfo->psBase;
+
+	seq_printf(s, "ID=%llu, refs=%u, WOPSnapshot=0x%x, parent=%p",
+				  psSync->psSyncData->ui64Stamp,
+				  atomic_read(&psSync->psSyncData->sRefcount),
+				  psSync->psSyncData->ui32WOPSnapshot,
+				  sync_pt_parent(&psSync->pt));
+	seq_printf(s, "\n   WOP/WOC=0x%x/0x%x, "
+	              "ROP/ROC=0x%x/0x%x, ROP2/ROC2=0x%x/0x%x, "
+	              "WOC DevVA=0x%.8x, ROC DevVA=0x%.8x, "
+	              "ROC2 DevVA=0x%.8x",
+	              psSyncInfo->psSyncData->ui32WriteOpsPending,
+	              psSyncInfo->psSyncData->ui32WriteOpsComplete,
+	              psSyncInfo->psSyncData->ui32ReadOpsPending,
+	              psSyncInfo->psSyncData->ui32ReadOpsComplete,
+	              psSyncInfo->psSyncData->ui32ReadOps2Pending,
+	              psSyncInfo->psSyncData->ui32ReadOps2Complete,
+	              psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+	              psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+	              psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr);
+}
+#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+static void PVRSyncPrintTimeline(struct sync_timeline *psObj,
+									char *str, int size)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline = (struct PVR_SYNC_TIMELINE *)psObj;
+
+	snprintf(str, size, "WOP/WOC=0x%x/0x%x",
+	           psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+	           psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete);
+}
+static void PVRSyncPrint(struct sync_pt *psPt, char *str, int size)
+{
+	struct PVR_SYNC *psSync = (struct PVR_SYNC *)psPt;
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+		psSync->psSyncData->psSyncInfo->psBase;
+
+	snprintf(str, size, "ID=%llu, refs=%u, WOPSnapshot=0x%x, parent=%p",
+				  psSync->psSyncData->ui64Stamp,
+				  atomic_read(&psSync->psSyncData->sRefcount),
+				  psSync->psSyncData->ui32WOPSnapshot,
+				  sync_pt_parent(&psSync->pt));//psSync->pt.parent);
+	snprintf(str, size, "\n   WOP/WOC=0x%x/0x%x, "
+	              "ROP/ROC=0x%x/0x%x, ROP2/ROC2=0x%x/0x%x, "
+	              "WOC DevVA=0x%.8x, ROC DevVA=0x%.8x, "
+	              "ROC2 DevVA=0x%.8x",
+	              psSyncInfo->psSyncData->ui32WriteOpsPending,
+	              psSyncInfo->psSyncData->ui32WriteOpsComplete,
+	              psSyncInfo->psSyncData->ui32ReadOpsPending,
+	              psSyncInfo->psSyncData->ui32ReadOpsComplete,
+	              psSyncInfo->psSyncData->ui32ReadOps2Pending,
+	              psSyncInfo->psSyncData->ui32ReadOps2Complete,
+	              psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+	              psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+	              psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr);
+}
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+
+static void PVRSyncReleaseTimeline(struct sync_timeline *psObj)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline = (struct PVR_SYNC_TIMELINE *)psObj;
+
+	mutex_lock(&gTimelineListLock);
+	list_del(&psTimeline->sTimelineList);
+	mutex_unlock(&gTimelineListLock);
+
+	DPF("R(t): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X "
+		"WOP/C=0x%x/0x%x ROP/C=0x%x/0x%x RO2P/C=0x%x/0x%x T=%p",
+		psTimeline->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psTimeline->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psTimeline->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+		psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+		psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete,
+		psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOpsPending,
+		psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOpsComplete,
+		psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOps2Pending,
+		psTimeline->psSyncInfo->psBase->psSyncData->ui32ReadOps2Complete,
+		psTimeline);
+
+	PVRSyncReleaseSyncInfo(psTimeline->psSyncInfo);
+	psTimeline->psSyncInfo = NULL;
+}
+
+PVRSRV_ERROR PVRSyncInitServices(void)
+{
+	IMG_BOOL bCreated, bShared[PVRSRV_MAX_CLIENT_HEAPS];
+	PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+	IMG_UINT32 ui32ClientHeapCount = 0;
+	PVRSRV_PER_PROCESS_DATA	*psPerProc;
+	PVRSRV_ERROR eError;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	gsSyncServicesConnection.ui32Pid = OSGetCurrentProcessIDKM();
+
+	eError = PVRSRVProcessConnect(gsSyncServicesConnection.ui32Pid, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVProcessConnect failed",
+								__func__));
+		goto err_unlock;
+	}
+
+	psPerProc = PVRSRVFindPerProcessData();
+	if (!psPerProc)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVFindPerProcessData failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	eError = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_SGX,
+									   &gsSyncServicesConnection.hDevCookie);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVAcquireDeviceDataKM failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	if (!gsSyncServicesConnection.hDevCookie)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: hDevCookie is NULL", __func__));
+		goto err_disconnect;
+	}
+
+	eError = PVRSRVCreateDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+	                                        psPerProc,
+											&gsSyncServicesConnection.hDevMemContext,
+											&ui32ClientHeapCount,
+											&sHeapInfo[0],
+											&bCreated,
+											&bShared[0]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVCreateDeviceMemContextKM failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	if (!gsSyncServicesConnection.hDevMemContext)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: hDevMemContext is NULL", __func__));
+		goto err_disconnect;
+	}
+
+err_unlock:
+	LinuxUnLockMutex(&gPVRSRVLock);
+	return eError;
+
+err_disconnect:
+	PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+	goto err_unlock;
+}
+
+void PVRSyncCloseServices(void)
+{
+	IMG_BOOL bDummy;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	PVRSRVDestroyDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+									gsSyncServicesConnection.hDevMemContext,
+									&bDummy);
+	gsSyncServicesConnection.hDevMemContext = NULL;
+	gsSyncServicesConnection.hDevCookie = NULL;
+
+	PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+	gsSyncServicesConnection.ui32Pid = 0;
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+static struct sync_timeline_ops gsTimelineOps =
+{
+	.driver_name		= "pvr_sync",
+	.dup				= PVRSyncDup,
+	.has_signaled		= PVRSyncHasSignaled,
+	.compare			= PVRSyncCompare,
+	.release_obj		= PVRSyncReleaseTimeline,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0))
+	.print_obj			= PVRSyncPrintTimeline,
+	.print_pt			= PVRSyncPrint,
+#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+	.timeline_value_str = PVRSyncPrintTimeline,
+	.pt_value_str       = PVRSyncPrint,
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) */
+	.free_pt			= PVRSyncFreeSync,
+};
+
+static struct PVR_SYNC_TIMELINE *PVRSyncCreateTimeline(const IMG_CHAR *pszName)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline;
+	PVRSRV_ERROR eError;
+
+	psTimeline = (struct PVR_SYNC_TIMELINE *)
+		sync_timeline_create(&gsTimelineOps, sizeof(struct PVR_SYNC_TIMELINE),
+							 pszName);
+	if (!psTimeline)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: sync_timeline_create failed", __func__));
+		goto err_out;
+	}
+
+	psTimeline->psSyncInfo =
+		kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if(!psTimeline->psSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+								"PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		goto err_free_timeline;
+	}
+
+	psTimeline->bSyncHasSignaled = IMG_FALSE;
+
+	mutex_init(&psTimeline->sTimelineLock);
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+	eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+								   gsSyncServicesConnection.hDevMemContext,
+								   &psTimeline->psSyncInfo->psBase);
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate timeline syncinfo",
+								__func__));
+		goto err_free_syncinfo;
+	}
+
+	DPF("A(t): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X T=%p %s",
+		psTimeline->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psTimeline->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psTimeline->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+		psTimeline, pszName);
+
+err_out:
+	return psTimeline;
+err_free_syncinfo:
+	kfree(psTimeline->psSyncInfo);
+err_free_timeline:
+	sync_timeline_destroy((struct sync_timeline *)psTimeline);
+	psTimeline = NULL;
+	goto err_out;
+}
+
+static int PVRSyncOpen(struct inode *inode, struct file *file)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline;
+	IMG_CHAR task_comm[TASK_COMM_LEN+1];
+
+	get_task_comm(task_comm, current);
+
+	psTimeline = PVRSyncCreateTimeline(task_comm);
+	if (!psTimeline)
+		return -ENOMEM;
+
+	mutex_lock(&gTimelineListLock);
+	list_add_tail(&psTimeline->sTimelineList, &gTimelineList);
+	mutex_unlock(&gTimelineListLock);
+
+	file->private_data = psTimeline;
+	return 0;
+}
+
+static int PVRSyncRelease(struct inode *inode, struct file *file)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline = file->private_data;
+	sync_timeline_destroy(&psTimeline->obj);
+	return 0;
+}
+
+static long
+PVRSyncIOCTLCreate(struct PVR_SYNC_TIMELINE *psObj, void __user *pvData)
+{
+	struct PVR_SYNC_KERNEL_SYNC_INFO *psProvidedSyncInfo = NULL;
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+	struct PVR_SYNC_CREATE_IOCTL_DATA sData;
+	int err = -EFAULT, iFd;
+	struct sync_fence *psFence;
+	struct sync_pt *psPt;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0))
+	iFd = get_unused_fd_flags(0);
+#else
+	iFd = get_unused_fd();
+#endif
+	if (iFd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+								__func__, iFd));
+		goto err_out;
+	}
+
+	if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (sData.allocdSyncInfo < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Requested to create a fence from "
+								" an invalid alloc'd fd (%d)", __func__,
+								sData.allocdSyncInfo));
+		goto err_put_fd;
+	}
+
+	psAllocSyncData = PVRSyncAllocFDGet(sData.allocdSyncInfo);
+	if (!psAllocSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSyncAllocFDGet returned NULL, "
+								"possibly fd passed to CREATE is not an "
+								"ALLOC'd sync?", __func__));
+		goto err_put_fd;
+	}
+
+	/* Move the psSyncInfo to the newly created sync, to avoid attempting
+	 * to create multiple syncs from the same allocation.
+	 */
+	psProvidedSyncInfo = psAllocSyncData->psSyncInfo;
+	psAllocSyncData->psSyncInfo = NULL;
+
+	if (psProvidedSyncInfo == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Alloc'd sync info is null - "
+								"possibly already CREATEd?", __func__));
+		fput(psAllocSyncData->psFile);
+		goto err_put_fd;
+	}
+
+	fput(psAllocSyncData->psFile);
+
+	psPt = (struct sync_pt *)PVRSyncCreateSync(psObj, psProvidedSyncInfo);
+	if (!psPt)
+	{
+		err = -ENOMEM;
+		goto err_put_fd;
+	}
+
+	sData.name[sizeof(sData.name) - 1] = '\0';
+	psFence = sync_fence_create(sData.name, psPt);
+	if (!psFence)
+	{
+		sync_pt_free(psPt);
+		err = -ENOMEM;
+		goto err_put_fd;
+	}
+
+	sData.fence = iFd;
+
+	if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+	{
+		sync_fence_put(psFence);
+		goto err_put_fd;
+	}
+
+	if (copy_to_user(pvData, &sData, sizeof(sData)))
+	{
+		sync_fence_put(psFence);
+		goto err_put_fd;
+	}
+
+	/* If the fence is a 'real' one, its signal status will be updated by
+	 * the MISR calling PVRSyncUpdateAllSyncs(). However, if we created
+	 * a 'fake' fence (for power optimization reasons) it has already
+	 * completed, and needs to be marked signalled (as the MISR will
+	 * never run for 'fake' fences).
+	 */
+	if(psProvidedSyncInfo->psBase->psSyncData->ui32WriteOpsPending == 0)
+		sync_timeline_signal((struct sync_timeline *)psObj);
+
+	DPF("C( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X F=%p %s",
+		psProvidedSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psProvidedSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psProvidedSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+		psFence, sData.name);
+
+	sync_fence_install(psFence, iFd);
+	err = 0;
+err_out:
+	return err;
+
+err_put_fd:
+	put_unused_fd(iFd);
+	goto err_out;
+}
+
+static long
+PVRSyncIOCTLDebug(struct PVR_SYNC_TIMELINE *psObj, void __user *pvData)
+{
+	struct PVR_SYNC_DEBUG_IOCTL_DATA sData;
+	struct sync_fence *psFence;
+	struct sync_pt *sync_pt;
+	int i = 0, j, err = -EFAULT;
+
+	if(!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_out;
+
+	if(copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_out;
+
+	psFence = sync_fence_fdget(sData.iFenceFD);
+	if(!psFence)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get fence from fd", __func__));
+		goto err_out;
+	}
+
+	for_each_sync_pt(sync_pt, psFence, j)
+	{
+		PVR_SYNC_DEBUG *psMetaData = &sData.sSync[i].sMetaData;
+		PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+		struct PVR_SYNC_TIMELINE *psTimeline;
+		struct PVR_SYNC *psPt;
+
+		if(i == PVR_SYNC_DEBUG_MAX_POINTS)
+		{
+			PVR_DPF((PVR_DBG_WARNING, "%s: Fence merged with more than %d "
+									  "points", __func__,
+									  PVR_SYNC_DEBUG_MAX_POINTS));
+			break;
+		}
+
+		psPt = (struct PVR_SYNC *)sync_pt; 
+
+		/* Don't dump foreign points */
+		if(sync_pt_parent(&psPt->pt)->ops != &gsTimelineOps)
+			continue;
+
+		psTimeline = (struct PVR_SYNC_TIMELINE *)sync_pt_parent(&psPt->pt);
+		psKernelSyncInfo = psPt->psSyncData->psSyncInfo->psBase;
+		PVR_ASSERT(psKernelSyncInfo != NULL);
+
+		/* The sync refcount is valid as long as the FenceFD stays open,
+		 * so we can access it directly without worrying about it being
+		 * freed.
+		 */
+		sData.sSync[i].sSyncData = *psKernelSyncInfo->psSyncData;
+
+		psMetaData->ui64Stamp                   = psPt->psSyncData->ui64Stamp;
+		psMetaData->ui32WriteOpsPendingSnapshot = psPt->psSyncData->ui32WOPSnapshot;
+		i++;
+	}
+
+	sync_fence_put(psFence);
+
+	sData.ui32NumPoints = i;
+
+	if(!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+		goto err_out;
+
+	if(copy_to_user(pvData, &sData, sizeof(sData)))
+		goto err_out;
+
+	err = 0;
+err_out:
+	return err;
+}
+
+static int PVRSyncFenceAllocRelease(struct inode *inode, struct file *file)
+{
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData = file->private_data;
+
+	if(psAllocSyncData->psSyncInfo)
+	{
+#if defined(DEBUG_PRINT)
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+			psAllocSyncData->psSyncInfo->psBase;
+#endif
+
+		DPF("R(a): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+			psSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->sReadOps2CompleteDevVAddr.uiAddr);
+
+		PVRSyncReleaseSyncInfo(psAllocSyncData->psSyncInfo);
+		psAllocSyncData->psSyncInfo = NULL;
+	}
+
+	kfree(psAllocSyncData);
+	return 0;
+}
+
+static const struct file_operations gsSyncFenceAllocFOps =
+{
+	.release = PVRSyncFenceAllocRelease,
+};
+
+struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd)
+{
+	struct file *file = fget(fd);
+	if (!file)
+		return NULL;
+	if (file->f_op != &gsSyncFenceAllocFOps)
+		goto err;
+	return file->private_data;
+err:
+	fput(file);
+	return NULL;
+}
+
+static long
+PVRSyncIOCTLAlloc(struct PVR_SYNC_TIMELINE *psTimeline, void __user *pvData)
+{
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+	int err = -EFAULT, iFd;
+	struct PVR_SYNC_ALLOC_IOCTL_DATA sData;
+	PVRSRV_SYNC_DATA *psSyncData;
+	struct file *psFile;
+	PVRSRV_ERROR eError;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0))
+	iFd = get_unused_fd_flags(0);
+#else
+	iFd = get_unused_fd();
+#endif
+	if (iFd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+		                        __func__, iFd));
+		goto err_out;
+	}
+
+	if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	psAllocSyncData = kmalloc(sizeof(struct PVR_ALLOC_SYNC_DATA), GFP_KERNEL);
+	if (!psAllocSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_ALLOC_SYNC_DATA",
+								__func__));
+		err = -ENOMEM;
+		goto err_put_fd;
+	}
+
+	psAllocSyncData->psSyncInfo =
+		kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if (!psAllocSyncData->psSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+								"PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		err = -ENOMEM;
+		goto err_free_alloc_sync_data;
+	}
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+	eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+	                               gsSyncServicesConnection.hDevMemContext,
+								   &psAllocSyncData->psSyncInfo->psBase);
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to alloc syncinfo (%d)",
+								__func__, eError));
+		err = -ENOMEM;
+		goto err_free_sync_info;
+	}
+
+	psFile = anon_inode_getfile("pvr_sync_alloc",
+								&gsSyncFenceAllocFOps, psAllocSyncData, 0);
+	if (!psFile)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create anon inode",
+								__func__));
+		err = -ENOMEM;
+		goto err_release_sync_info;
+	}
+
+	sData.fence = iFd;
+
+	/* Check if this timeline looks idle. If there are still TQs running
+	 * on it, userspace shouldn't attempt any kind of power optimization
+	 * (e.g. it must not dummy-process GPU fences).
+	 *
+	 * Determining idleness here is safe because the ALLOC and CREATE
+	 * pvr_sync ioctls must be called under the gralloc module lock, so
+	 * we can't be creating another new fence op while we are still
+	 * processing this one.
+	 *
+ 	 * Take the bridge lock anyway so we can be sure that we read the
+	 * timeline sync's pending value coherently. The complete value may
+	 * be modified by the GPU, but worse-case we will decide we can't do
+	 * the power optimization and will still be correct.
+	 */
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	psSyncData = psTimeline->psSyncInfo->psBase->psSyncData;
+	if(psSyncData->ui32WriteOpsPending == psSyncData->ui32WriteOpsComplete)
+		sData.bTimelineIdle = IMG_TRUE;
+	else
+		sData.bTimelineIdle = IMG_FALSE;
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+		goto err_release_file;
+
+	if (copy_to_user(pvData, &sData, sizeof(sData)))
+		goto err_release_file;
+
+	psAllocSyncData->psTimeline = psTimeline;
+	psAllocSyncData->psFile = psFile;
+
+	DPF("A( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+		psAllocSyncData->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psAllocSyncData->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psAllocSyncData->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+	fd_install(iFd, psFile);
+	err = 0;
+err_out:
+	return err;
+err_release_sync_info:
+	PVRSRVReleaseSyncInfoKM(psAllocSyncData->psSyncInfo->psBase);
+err_free_sync_info:
+	kfree(psAllocSyncData->psSyncInfo);
+err_free_alloc_sync_data:
+	kfree(psAllocSyncData);
+err_put_fd:
+	put_unused_fd(iFd);
+	goto err_out;
+err_release_file:
+	fput(psFile);
+	put_unused_fd(iFd);
+	goto err_out;
+}
+
+static long
+PVRSyncIOCTL(struct file *file, unsigned int cmd, unsigned long __user arg)
+{
+	struct PVR_SYNC_TIMELINE *psTimeline = file->private_data;
+	void __user *pvData = (void __user *)arg;
+
+	switch (cmd)
+	{
+		case PVR_SYNC_IOC_CREATE_FENCE:
+			return PVRSyncIOCTLCreate(psTimeline, pvData);
+		case PVR_SYNC_IOC_DEBUG_FENCE:
+			return PVRSyncIOCTLDebug(psTimeline, pvData);
+		case PVR_SYNC_IOC_ALLOC_FENCE:
+			return PVRSyncIOCTLAlloc(psTimeline, pvData);
+		default:
+			return -ENOTTY;
+	}
+}
+
+static void PVRSyncWorkQueueFunction(struct work_struct *data)
+{
+	PVRSRV_DEVICE_NODE *psDevNode =
+		(PVRSRV_DEVICE_NODE*)gsSyncServicesConnection.hDevCookie;
+	struct list_head sFreeList, *psEntry, *n;
+	unsigned long flags;
+
+	/* We lock the bridge mutex here for two reasons.
+	 *
+	 * Firstly, the SGXScheduleProcessQueuesKM and PVRSRVReleaseSyncInfoKM
+	 * functions require that they are called under lock. Multiple threads
+	 * into services are not allowed.
+	 *
+	 * Secondly, we need to ensure that when processing the defer-free list,
+	 * the PVRSyncIsSyncInfoInUse() function is called *after* any freed
+	 * sync was attached as a HW dependency (had ROP/ROP2 taken). This is
+	 * because for 'foreign' sync timelines we allocate a new object and
+	 * mark it for deletion immediately. If the 'foreign' sync_pt signals
+	 * before the kick ioctl has completed, we can block it from being
+	 * prematurely freed by holding the bridge mutex.
+	 *
+	 * NOTE: This code relies on the assumption that we can acquire a
+	 * spinlock while a mutex is held and that other users of the spinlock
+	 * do not need to hold the bridge mutex.
+	 */
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	/* A completed SW operation may un-block the GPU */
+	SGXScheduleProcessQueuesKM(psDevNode);
+
+	/* We can't call PVRSRVReleaseSyncInfoKM directly in this loop because
+	 * that will take the mmap mutex. We can't take mutexes while we have
+	 * this list locked with a spinlock. So move all the items we want to
+	 * free to another, local list (no locking required) and process it
+	 * in a second loop.
+	 */
+
+	INIT_LIST_HEAD(&sFreeList);
+	spin_lock_irqsave(&gSyncInfoFreeListLock, flags);
+	list_for_each_safe(psEntry, n, &gSyncInfoFreeList)
+	{
+		struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+			container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		if(!PVRSyncIsSyncInfoInUse(psSyncInfo->psBase))
+			list_move_tail(psEntry, &sFreeList);
+
+	}
+	spin_unlock_irqrestore(&gSyncInfoFreeListLock, flags);
+
+	list_for_each_safe(psEntry, n, &sFreeList)
+	{
+		struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+			container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		list_del(psEntry);
+
+		DPF("F(d): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+			psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+		PVRSRVReleaseSyncInfoKM(psSyncInfo->psBase);
+		psSyncInfo->psBase = NULL;
+
+		kfree(psSyncInfo);
+	}
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	/* Copying from one list to another (so a spinlock isn't held) used to
+	 * work around the problem that PVRSyncReleaseSyncInfo() would hold the
+	 * services mutex. However, we no longer do this, so this code could
+	 * potentially be simplified.
+	 *
+	 * Note however that sync_fence_put must be called from process/WQ
+	 * context because it uses fput(), which is not allowed to be called
+	 * from interrupt context in kernels <3.6.
+	 */
+	INIT_LIST_HEAD(&sFreeList);
+	spin_lock_irqsave(&gFencePutListLock, flags);
+	list_for_each_safe(psEntry, n, &gFencePutList)
+	{
+		list_move_tail(psEntry, &sFreeList);
+	}
+	spin_unlock_irqrestore(&gFencePutListLock, flags);
+
+	list_for_each_safe(psEntry, n, &sFreeList)
+	{
+		struct PVR_SYNC_FENCE *psSyncFence =
+			container_of(psEntry, struct PVR_SYNC_FENCE, sHead);
+
+		list_del(psEntry);
+
+		sync_fence_put(psSyncFence->psBase);
+		psSyncFence->psBase = NULL;
+
+		kfree(psSyncFence);
+	}
+}
+
+static const struct file_operations gsPVRSyncFOps =
+{
+	.owner			= THIS_MODULE,
+	.open			= PVRSyncOpen,
+	.release		= PVRSyncRelease,
+	.unlocked_ioctl	= PVRSyncIOCTL,
+	.compat_ioctl   = PVRSyncIOCTL,
+};
+
+static struct miscdevice gsPVRSyncDev =
+{
+	.minor			= MISC_DYNAMIC_MINOR,
+	.name			= "pvr_sync",
+	.fops			= &gsPVRSyncFOps,
+};
+
+IMG_INTERNAL
+int PVRSyncDeviceInit(void)
+{
+	int err = -1;
+
+	if(PVRSyncInitServices() != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise services",
+								__func__));
+		goto err_out;
+	}
+
+	gpsWorkQueue = create_freezable_workqueue("pvr_sync_workqueue");
+	if(!gpsWorkQueue)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create pvr_sync workqueue",
+								__func__));
+		goto err_deinit_services;
+	}
+
+	INIT_WORK(&gsWork, PVRSyncWorkQueueFunction);
+
+	err = misc_register(&gsPVRSyncDev);
+	if(err)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to register pvr_sync misc "
+								"device (err=%d)", __func__, err));
+		goto err_deinit_services;
+	}
+
+	err = 0;
+err_out:
+	return err;
+err_deinit_services:
+	PVRSyncCloseServices();
+	goto err_out;
+}
+
+IMG_INTERNAL
+void PVRSyncDeviceDeInit(void)
+{
+	misc_deregister(&gsPVRSyncDev);
+	destroy_workqueue(gpsWorkQueue);
+	PVRSyncCloseServices();
+}
+
+IMG_INTERNAL
+void PVRSyncUpdateAllSyncs(void)
+{
+	IMG_BOOL bNeedToProcessQueues = IMG_FALSE;
+	struct list_head *psEntry;
+
+	/* Check to see if any syncs have signalled. If they have, it may unblock
+	 * the GPU. Decide what is needed and optionally schedule queue
+	 * processing.
+	 */
+	mutex_lock(&gTimelineListLock);
+	list_for_each(psEntry, &gTimelineList)
+	{
+		struct PVR_SYNC_TIMELINE *psTimeline =
+			container_of(psEntry, struct PVR_SYNC_TIMELINE, sTimelineList);
+
+		sync_timeline_signal((struct sync_timeline *)psTimeline);
+
+		if(psTimeline->bSyncHasSignaled)
+		{
+			psTimeline->bSyncHasSignaled = IMG_FALSE;
+			bNeedToProcessQueues = IMG_TRUE;
+		}
+	}
+	mutex_unlock(&gTimelineListLock);
+
+	if(bNeedToProcessQueues)
+		queue_work(gpsWorkQueue, &gsWork);
+}
+
+static IMG_BOOL
+PVRSyncIsDuplicate(PVRSRV_KERNEL_SYNC_INFO *psA, PVRSRV_KERNEL_SYNC_INFO *psB)
+{
+	return psA->sWriteOpsCompleteDevVAddr.uiAddr ==
+		   psB->sWriteOpsCompleteDevVAddr.uiAddr ? IMG_TRUE : IMG_FALSE;
+}
+
+static void ForeignSyncPtSignaled(struct sync_fence *fence,
+								  struct sync_fence_waiter *waiter)
+{
+	struct PVR_SYNC_FENCE_WAITER *psWaiter =
+		(struct PVR_SYNC_FENCE_WAITER *)waiter;
+	unsigned long flags;
+
+	PVRSyncSWCompleteOp(psWaiter->psSyncInfo->psBase);
+
+	DPF("R(f): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X "
+		"WOP/C=0x%x/0x%x ROP/C=0x%x/0x%x RO2P/C=0x%x/0x%x",
+		psWaiter->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psWaiter->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psWaiter->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+		psWaiter->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending,
+		psWaiter->psSyncInfo->psBase->psSyncData->ui32WriteOpsComplete,
+		psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOpsPending,
+		psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOpsComplete,
+		psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOps2Pending,
+		psWaiter->psSyncInfo->psBase->psSyncData->ui32ReadOps2Complete);
+
+	PVRSyncReleaseSyncInfo(psWaiter->psSyncInfo);
+	psWaiter->psSyncInfo = NULL;
+
+	/* We can 'put' the fence now, but this function might be called in irq
+	 * context so we must defer to WQ.
+	 */
+	spin_lock_irqsave(&gFencePutListLock, flags);
+	list_add_tail(&psWaiter->psSyncFence->sHead, &gFencePutList);
+	psWaiter->psSyncFence = NULL;
+	spin_unlock_irqrestore(&gFencePutListLock, flags);
+
+	/* The PVRSyncReleaseSyncInfo() call above already queued work */
+	/*queue_work(gpsWorkQueue, &gsWork);*/
+
+	kfree(psWaiter);
+}
+
+static PVRSRV_KERNEL_SYNC_INFO *ForeignSyncPointToSyncInfo(int iFenceFd)
+{
+	PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+	struct PVR_SYNC_FENCE_WAITER *psWaiter;
+	struct PVR_SYNC_FENCE *psSyncFence;
+	struct sync_fence *psFence;
+	PVRSRV_ERROR eError;
+	int err;
+
+	/* FIXME: Could optimize this function by pre-testing sync_wait(.., 0)
+	 *        to determine if it has already signalled. We must avoid this
+	 *        for now because the sync driver was broken in earlier kernels.
+	 */
+
+	/* The custom waiter structure is freed in the waiter callback */
+	psWaiter = kmalloc(sizeof(struct PVR_SYNC_FENCE_WAITER), GFP_KERNEL);
+	if(!psWaiter)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate waiter", __func__));
+		goto err_out;
+	}
+
+	psWaiter->psSyncInfo =
+		kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if(!psWaiter->psSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+								"PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		goto err_free_waiter;
+	}
+
+	/* We take another reference on the parent fence, each time we see a
+	 * 'foreign' sync_pt. This is to ensure the timeline, fence and sync_pts
+	 * from the foreign timeline cannot go away until the sync_pt signals.
+	 * In practice this also means they will not go away until the entire
+	 * fence signals. It means that we will always get a
+	 * sync_fence_wait_async() callback for these points.
+	 */
+	psFence = sync_fence_fdget(iFenceFd);
+	if(!psFence)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to take reference on fence",
+								__func__));
+		goto err_free_syncinfo;
+	}
+
+	/* Allocate packet we can store this fence on (with a list head) so we
+	 * can add it to the defer-put list without allocating memory in irq
+	 * context.
+	 *
+	 * NOTE: At the moment we allocate one of these per sync_pts, but it
+	 * might be possible to optimize this to one per fence.
+	 */
+	psSyncFence = kmalloc(sizeof(struct PVR_SYNC_FENCE), GFP_KERNEL);
+	if(!psSyncFence)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+								"PVR_SYNC_FENCE", __func__));
+		goto err_sync_fence_put;
+	}
+
+	psSyncFence->psBase = psFence;
+	psWaiter->psSyncFence = psSyncFence;
+
+	/* Allocate a "shadow" SYNCINFO for this sync_pt and set it up to be
+	 * completed by the callback.
+	 */
+	eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+								   gsSyncServicesConnection.hDevMemContext,
+								   &psKernelSyncInfo);
+	if(eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate syncinfo", __func__));
+		goto err_free_sync_fence;
+	}
+
+	/* Make sure we take the SW operation before adding the waiter, to avoid
+	 * racing with parallel completes.
+	 */
+	PVRSyncSWTakeOp(psKernelSyncInfo);
+
+	sync_fence_waiter_init(&psWaiter->sWaiter, ForeignSyncPtSignaled);
+	psWaiter->psSyncInfo->psBase = psKernelSyncInfo;
+
+	err = sync_fence_wait_async(psFence, &psWaiter->sWaiter);
+	if(err)
+	{
+		if(err < 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Fence was in error state", __func__));
+			/* Fall-thru */
+		}
+
+		/* -1 means the fence was broken, 1 means the fence already
+		 * signalled. In either case, roll back what we've done and
+		 * skip using this sync_pt for synchronization.
+		 */
+		goto err_release_sync_info;
+	}
+
+	DPF("A(f): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X F=%p",
+		psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr,
+		psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr,
+		psKernelSyncInfo->sReadOps2CompleteDevVAddr.uiAddr,
+		psFence);
+
+	/* NOTE: Don't use psWaiter after this point as it may asynchronously
+	 * signal before this function completes (and be freed already).
+	 */
+
+	/* Even if the fence signals while we're hanging on to this, the sync
+	 * can't be freed until the bridge mutex is taken in the callback. The
+	 * bridge mutex won't be released by the caller of this function until
+	 * the GPU operation has been scheduled, which increments ROP,
+	 * preventing the sync from being freed when still in use by the GPU.
+	 */
+	return psKernelSyncInfo;
+
+err_release_sync_info:
+	PVRSyncSWCompleteOp(psKernelSyncInfo);
+	PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+err_free_sync_fence:
+	kfree(psSyncFence);
+err_sync_fence_put:
+	sync_fence_put(psFence);
+err_free_syncinfo:
+	kfree(psWaiter->psSyncInfo);
+err_free_waiter:
+	kfree(psWaiter);
+err_out:
+	return NULL;
+}
+
+static IMG_BOOL FenceHasForeignPoints(struct sync_fence *psFence)
+{
+	struct sync_pt *psPt;
+	int j;
+
+	for_each_sync_pt(psPt, psFence, j)
+	{
+		if(sync_pt_parent(psPt)->ops != &gsTimelineOps)
+			return IMG_TRUE;
+	}
+
+	return IMG_FALSE;
+}
+
+IMG_BOOL
+ExpandAndDeDuplicateFenceSyncs(IMG_UINT32 ui32NumSyncs,
+							   IMG_HANDLE aiFenceFds[],
+							   IMG_UINT32 ui32SyncPointLimit,
+							   struct sync_fence *apsFence[],
+							   IMG_UINT32 *pui32NumRealSyncs,
+							   PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[])
+{
+	IMG_UINT32 i, j, ui32FenceIndex = 0;
+	IMG_BOOL bRet = IMG_TRUE;
+	struct sync_pt *psPt;
+
+	*pui32NumRealSyncs = 0;
+
+	for(i = 0; i < ui32NumSyncs; i++)
+	{
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+
+		/* Skip any invalid fence file descriptors without error */
+		if((IMG_INT32)aiFenceFds[i] < 0)
+			continue;
+
+		/* By converting a file descriptor to a struct sync_fence, we are
+		 * taking a reference on the fence. We don't want the fence to go
+		 * away until we have submitted the command, even if it signals
+		 * before we dispatch the command, or the timeline(s) are destroyed.
+		 *
+		 * This reference should be released by the caller of this function
+		 * once hardware operations have been scheduled on the GPU sync_pts
+		 * participating in this fence. When our MISR is scheduled, the
+		 * defer-free list will be processed, cleaning up the SYNCINFO.
+		 *
+		 * Note that this reference *isn't* enough for non-GPU sync_pts.
+		 * We'll take another reference on the fence for those operations
+		 * later (the life-cycle requirements there are totally different).
+		 *
+		 * Fence lookup may fail here if the fd became invalid since it was
+		 * patched in userspace. That's really a userspace driver bug, so
+		 * just fail here instead of not synchronizing.
+		 */
+		apsFence[ui32FenceIndex] = sync_fence_fdget((IMG_INT32)aiFenceFds[i]);
+		if(!apsFence[ui32FenceIndex])
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get fence from fd=%d",
+									__func__, (IMG_SIZE_T)aiFenceFds[i]));
+			bRet = IMG_FALSE;
+			goto err_out;
+		}
+
+		/* If this fence has any points from foreign timelines, we need to
+		 * allocate a 'shadow' SYNCINFO and update it in software ourselves,
+		 * so the ukernel can test the readiness of the dependency.
+		 *
+		 * It's tempting to just handle all fences like this (since most of
+		 * the time they *will* be merged with sw_sync) but such 'shadow'
+		 * syncs are slower. This is because we need to wait for the MISR to
+		 * schedule to update the GPU part of the fence (normally the ukernel
+		 * would be able to make the update directly).
+		 */
+		if(FenceHasForeignPoints(apsFence[ui32FenceIndex]))
+		{
+			psSyncInfo = ForeignSyncPointToSyncInfo((IMG_INT32)aiFenceFds[i]);
+			if(psSyncInfo)
+			{
+				if(!AddSyncInfoToArray(psSyncInfo, ui32SyncPointLimit,
+									   pui32NumRealSyncs, apsSyncInfo))
+				{
+					/* Soft-fail. Stop synchronizing. */
+					goto err_out;
+				}
+			}
+			ui32FenceIndex++;
+			continue;
+		}
+
+		/* FIXME: The ForeignSyncPointToSyncInfo() path optimizes away already
+		 *        signalled fences. Consider optimizing this path too.
+		 */
+		for_each_sync_pt(psPt, apsFence[ui32FenceIndex], j)
+		{
+
+			psSyncInfo =
+				((struct PVR_SYNC *)psPt)->psSyncData->psSyncInfo->psBase;
+
+			/* Walk the current list of points and make sure this isn't a
+			 * duplicate. Duplicates will deadlock.
+			 */
+			for(j = 0; j < *pui32NumRealSyncs; j++)
+			{
+				/* The point is from a different timeline so we must use it */
+				if(!PVRSyncIsDuplicate(apsSyncInfo[j], psSyncInfo))
+					continue;
+
+				/* There's no need to bump the real sync count as we either
+				 * ignored the duplicate or replaced an previously counted
+				 * entry.
+			 	 */
+				break;
+			}
+
+			if(j == *pui32NumRealSyncs)
+			{
+				/* It's not a duplicate; moving on.. */
+				if(!AddSyncInfoToArray(psSyncInfo, ui32SyncPointLimit,
+									   pui32NumRealSyncs, apsSyncInfo))
+					goto err_out;
+			}
+		}
+
+		ui32FenceIndex++;
+	}
+
+err_out:
+	return bRet;
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.h
new file mode 100644
index 0000000..853586b
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync.h
@@ -0,0 +1,201 @@
+/*************************************************************************/ /*!
+@File           pvr_sync.c
+@Title          Kernel driver for Android's sync mechanism
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* This is the IMG extension of a sync_timeline */
+
+struct PVR_SYNC_TIMELINE
+{
+	struct sync_timeline				obj;
+
+	/* Needed to keep a global list of all timelines for MISR checks. */
+	struct list_head					sTimelineList;
+
+	/* True if a sync point on the timeline has signaled */
+	IMG_BOOL							bSyncHasSignaled;
+
+	/* A mutex, as we want to ensure that the comparison (and possible
+	 * reset) of the highest SW fence value is atomic with the takeop,
+	 * so both the SW fence value and the WOP snapshot should both have
+	 * the same order for all SW syncs.
+	 *
+	 * This mutex also protects modifications to the fence stamp counter.
+	 */
+	struct mutex						sTimelineLock;
+
+	/* Every timeline has a services sync object. This object must not
+	 * be used by the hardware to enforce ordering -- that's what the
+	 * per sync-point objects are for. This object is attached to every
+	 * TQ scheduled on the timeline and is primarily useful for debugging.
+	 */
+	struct PVR_SYNC_KERNEL_SYNC_INFO	*psSyncInfo;
+};
+
+/* A PVR_SYNC_DATA is the basic guts of a sync point. It's kept separate
+ * because sync points can be dup'ed, and we don't want to duplicate all
+ * of the shared metadata.
+ *
+ * This is also used to back an allocated sync info, which can be passed to
+ * the CREATE ioctl to insert the fence and add it to the timeline. This is
+ * used as an intermediate step as a PVRSRV_KERNEL_SYNC_INFO is needed to
+ * attach to the transfer task used as a fence in the hardware.
+ */
+
+struct PVR_SYNC_DATA
+{
+	/* Every sync point has a services sync object. This object is used
+	 * by the hardware to enforce ordering -- it is attached as a source
+	 * dependency to various commands.
+	 */
+	struct PVR_SYNC_KERNEL_SYNC_INFO	*psSyncInfo;
+
+	/* This refcount is incremented at create and dup time, and decremented
+	 * at free time. It ensures the object doesn't start the defer-free
+	 * process until it is no longer referenced.
+	 */
+	atomic_t							sRefcount;
+
+	/* This is purely a debug feature. Record the WOP snapshot from the
+	 * timeline synchronization object when a new fence is created.
+	 */
+	IMG_UINT32							ui32WOPSnapshot;
+
+	/* This is a globally unique ID for the sync point. If a sync point is
+	 * duplicated, its stamp is copied over (seems counter-intuitive, but in
+	 * nearly all cases a sync point is merged with another, the original
+	 * is freed).
+	 */
+	IMG_UINT64							ui64Stamp;
+};
+
+/* This is the IMG extension of a sync_pt */
+
+struct PVR_SYNC
+{
+	struct sync_pt			pt;
+	struct PVR_SYNC_DATA	*psSyncData;
+};
+
+struct PVR_SYNC_FENCE
+{
+	/* Base sync_fence structure */
+	struct sync_fence	*psBase;
+
+	/* To ensure callbacks are always received for fences / sync_pts, even
+	 * after the fence has been 'put' (freed), we must take a reference to
+	 * the fence. We still need to 'put' the fence ourselves, but this might
+	 * happen in irq context, where fput() is not allowed (in kernels <3.6).
+	 * We must add the fence to a list which is processed in WQ context.
+	 */
+	struct list_head	sHead;
+};
+
+/* Any sync point from a foreign (non-PVR) timeline needs to have a "shadow"
+ * syncinfo. This is modelled as a software operation. The foreign driver
+ * completes the operation by calling a callback we registered with it.
+ *
+ * Because we are allocating SYNCINFOs for each sync_pt, rather than each
+ * fence, we need to extend the waiter struct slightly to include the
+ * necessary metadata.
+ */
+struct PVR_SYNC_FENCE_WAITER
+{
+	/* Base sync driver waiter structure */
+	struct sync_fence_waiter			sWaiter;
+
+	/* "Shadow" syncinfo backing the foreign driver's sync_pt */
+	struct PVR_SYNC_KERNEL_SYNC_INFO	*psSyncInfo;
+
+	/* Optimizes lookup of fence for defer-put operation */
+	struct PVR_SYNC_FENCE				*psSyncFence;
+};
+
+/* Local wrapper around PVRSRV_KERNEL_SYNC_INFO to add a list head */
+
+struct PVR_SYNC_KERNEL_SYNC_INFO
+{
+	/* Base services sync info structure */
+	PVRSRV_KERNEL_SYNC_INFO	*psBase;
+
+	/* Sync points can go away when there are deferred hardware
+	 * operations still outstanding. We must not free the SYNC_INFO
+	 * until the hardware is finished, so we add it to a defer list
+	 * which is processed periodically ("defer-free").
+	 *
+	 * This is also used for "defer-free" of a timeline -- the process
+	 * may destroy its timeline or terminate abnormally but the HW could
+	 * still be using the sync object hanging off of the timeline.
+	 *
+	 * Note that the defer-free list is global, not per-timeline.
+	 */
+	struct list_head		sHead;
+};
+
+/* A PVR_ALLOC_SYNC_DATA is used to back an allocated, but not yet created
+ * and inserted into a timeline, sync data. This is required as we must
+ * allocate the syncinfo to be passed down with the transfer task used to
+ * implement fences in the hardware.
+ */
+struct PVR_ALLOC_SYNC_DATA
+{
+	struct PVR_SYNC_KERNEL_SYNC_INFO	*psSyncInfo;
+
+	/* A link to the timeline is required to add a per-timeline sync
+	 * to the fence transfer task.
+	 */
+	struct PVR_SYNC_TIMELINE			*psTimeline;
+	struct file							*psFile;
+};
+
+
+IMG_BOOL
+ExpandAndDeDuplicateFenceSyncs(IMG_UINT32 ui32NumSyncs,
+							   IMG_HANDLE aiFenceFds[],
+							   IMG_UINT32 ui32SyncPointLimit,
+							   struct sync_fence *apsFence[],
+							   IMG_UINT32 *pui32NumRealSyncs,
+							   PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[]);
+
+PVRSRV_ERROR PVRSyncInitServices(void);
+void PVRSyncCloseServices(void);
+
+struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd);
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_common.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_common.c
new file mode 100644
index 0000000..b9120c1
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_common.c
@@ -0,0 +1,379 @@
+/*************************************************************************/ /*!
+@File           pvr_sync.c
+@Title          Kernel driver for Android's sync mechanism
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "pvr_sync_common.h"
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+#include "pvr_sync.h"
+#else
+#include "pvr_fence.h"
+#endif
+
+#include <linux/kernel.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/anon_inodes.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+#include "sgxutils.h"
+#include "ttrace.h"
+#include "mutex.h"
+#include "lock.h"
+
+static void
+CopyKernelSyncInfoToDeviceSyncObject(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+				     PVRSRV_DEVICE_SYNC_OBJECT *psSyncObject)
+{
+	psSyncObject->sReadOpsCompleteDevVAddr  = psSyncInfo->sReadOpsCompleteDevVAddr;
+	psSyncObject->sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+	psSyncObject->sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
+	psSyncObject->ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+	psSyncObject->ui32ReadOpsPendingVal  = psSyncInfo->psSyncData->ui32ReadOpsPending;
+	psSyncObject->ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+}
+
+IMG_BOOL
+AddSyncInfoToArray(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+				   IMG_UINT32 ui32SyncPointLimit,
+				   IMG_UINT32 *pui32NumRealSyncs,
+				   PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[])
+{
+	/* Ran out of syncs. Not much userspace can do about this, since it
+	 * could have been passed multiple merged syncs and doesn't know they
+	 * were merged. Allow this through, but print a warning and stop
+	 * synchronizing.
+	 */
+	if(*pui32NumRealSyncs == ui32SyncPointLimit)
+	{
+		PVR_DPF((PVR_DBG_WARNING, "%s: Ran out of source syncs %d == %d",
+								  __func__, *pui32NumRealSyncs,
+								  ui32SyncPointLimit));
+		return IMG_FALSE;
+	}
+
+	apsSyncInfo[*pui32NumRealSyncs] = psSyncInfo;
+	(*pui32NumRealSyncs)++;
+	return IMG_TRUE;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+PVRSyncPatchCCBKickSyncInfos(IMG_HANDLE    ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+		      PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+							 IMG_UINT32 *pui32NumSrcSyncs)
+{
+	PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	struct sync_fence *apsFence[SGX_MAX_SRC_SYNCS_TA] = {};
+#else  /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE) */
+	struct dma_fence *apsFence[SGX_MAX_SRC_SYNCS_TA] = {};
+#endif
+	IMG_UINT32 i, ui32NumRealSrcSyncs;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if(!ExpandAndDeDuplicateFenceSyncs(*pui32NumSrcSyncs,
+									   (IMG_HANDLE *)ahSyncs,
+									   SGX_MAX_SRC_SYNCS_TA,
+									   apsFence,
+									   &ui32NumRealSrcSyncs,
+									   apsSyncInfo))
+	{
+		eError = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+		goto err_put_fence;
+	}
+
+	/* There should only be one destination sync for a transfer.
+	 * Ultimately this will be patched to two (the sync_pt SYNCINFO,
+	 * and the timeline's SYNCINFO for debugging).
+	 */
+	for(i = 0; i < ui32NumRealSrcSyncs; i++)
+	{
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = apsSyncInfo[i];
+
+		/* The following code is mostly the same as the texture dependencies
+		 * handling in SGXDoKickKM, but we have to copy it here because it
+		 * must be run while the fence is 'locked' by sync_fence_fdget.
+		 */
+
+		PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_SRC_SYNC,
+				       psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+		CopyKernelSyncInfoToDeviceSyncObject(psSyncInfo, &asDevSyncs[i]);
+
+		/* Texture dependencies are read operations */
+		psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+		/* Finally, patch the sync back into the input array.
+		 * NOTE: The syncs are protected here by the defer-free worker.
+		 */
+		ahSyncs[i] = psSyncInfo;
+	}
+
+	/* Updating this allows the PDUMP handling and ROP rollbacks to work
+	 * correctly in SGXDoKickKM.
+	 */
+	*pui32NumSrcSyncs = ui32NumRealSrcSyncs;
+
+err_put_fence:
+	for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+		sync_fence_put(apsFence[i]);
+#else
+		dma_fence_put(apsFence[i]);
+#endif
+	return eError;
+}
+
+/* Patching for TQ fence in queueBuffer() */
+IMG_INTERNAL PVRSRV_ERROR
+PVRSyncPatchTransferSyncInfos(IMG_HANDLE    ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+			      PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+							     IMG_UINT32 *pui32NumSrcSyncs)
+{
+	struct PVR_ALLOC_SYNC_DATA *psTransferSyncData;
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (*pui32NumSrcSyncs != 1)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Invalid number of syncs (%d), clamping "
+								"to 1", __func__, *pui32NumSrcSyncs));
+	}
+
+	psTransferSyncData = PVRSyncAllocFDGet((int)ahSyncs[0]);
+
+	if (!psTransferSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get PVR_SYNC_DATA from "
+								"supplied fd", __func__));
+		eError = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+		goto err_out;
+	}
+
+	/* There should only be one destination sync for a transfer.
+	 * Ultimately this will be patched to two (the sync_pt SYNCINFO,
+	 * and the timeline's SYNCINFO for debugging).
+	 */
+	psSyncInfo = psTransferSyncData->psSyncInfo->psBase;
+
+	/* The following code is mostly the same as the texture dependencies
+	 * handling in SGXDoKickKM, but we have to copy it here because it
+	 * must be run while the fence is 'locked' by sync_fence_fdget.
+	 */
+
+	PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_SRC_SYNC,
+			       psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
+
+	CopyKernelSyncInfoToDeviceSyncObject(psSyncInfo, &asDevSyncs[0]);
+	CopyKernelSyncInfoToDeviceSyncObject(psTransferSyncData->psTimeline->psSyncInfo->psBase,
+					     &asDevSyncs[1]);
+
+	/* Treat fence TQs as write operations */
+	psSyncInfo->psSyncData->ui32WriteOpsPending++;
+	psTransferSyncData->psTimeline->psSyncInfo->psBase->psSyncData->ui32WriteOpsPending++;
+
+	/* Finally, patch the sync back into the input array.
+	 * NOTE: The syncs are protected here by the defer-free worker.
+	 */
+	ahSyncs[0] = psSyncInfo;
+	ahSyncs[1] = psTransferSyncData->psTimeline->psSyncInfo->psBase;
+
+	/* Updating this allows the PDUMP handling and ROP rollbacks to work
+	 * correctly in SGXDoKickKM.
+	 */
+	*pui32NumSrcSyncs = 2;
+
+	fput(psTransferSyncData->psFile);
+err_out:
+	return eError;
+}
+
+
+/* NOTE: This returns an array of sync_fences which need to be 'put'
+ *       or they will leak.
+ */
+/* Display side patching */
+IMG_INTERNAL PVRSRV_ERROR
+PVRSyncFencesToSyncInfos(PVRSRV_KERNEL_SYNC_INFO *apsSyncs[],
+						 IMG_UINT32 *pui32NumSyncs,
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+						 struct sync_fence *apsFence[SGX_MAX_SRC_SYNCS_TA]
+#else /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE) */
+						 struct dma_fence *apsFence[SGX_MAX_SRC_SYNCS_TA]
+#endif
+						 )
+{
+	PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[SGX_MAX_SRC_SYNCS_TA];
+	IMG_UINT32 i, ui32NumRealSrcSyncs;
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+	memset(apsFence, 0, sizeof(struct sync_fence *) * SGX_MAX_SRC_SYNCS_TA);
+#else /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE) */
+	memset(apsFence, 0, sizeof(struct dma_fence *) * SGX_MAX_SRC_SYNCS_TA);
+#endif
+
+	if(!ExpandAndDeDuplicateFenceSyncs(*pui32NumSyncs,
+									   (IMG_HANDLE *)apsSyncs,
+									   *pui32NumSyncs,
+									   apsFence,
+									   &ui32NumRealSrcSyncs,
+									   apsSyncInfo))
+	{
+		for(i = 0; i < SGX_MAX_SRC_SYNCS_TA && apsFence[i]; i++)
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+			sync_fence_put(apsFence[i]);
+#else /* defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE) */
+			dma_fence_put(apsFence[i]);
+#endif
+
+		return PVRSRV_ERROR_HANDLE_NOT_FOUND;
+	}
+
+	/* We don't expect to see merged syncs here. Abort if that happens.
+	 * Allow through cases where the same fence was specified more than
+	 * once -- we can handle that without reallocation of memory.
+	 */
+	PVR_ASSERT(ui32NumRealSrcSyncs <= *pui32NumSyncs);
+
+	for(i = 0; i < ui32NumRealSrcSyncs; i++)
+		apsSyncs[i] = apsSyncInfo[i];
+
+	*pui32NumSyncs = ui32NumRealSrcSyncs;
+	//PVR_DPF((PVR_DBG_ERROR, "%s END HERE", __func__));
+	return eError;
+}
+
+/*PVRSRV_ERROR PVRSyncInitServices(void)
+{
+	IMG_BOOL bCreated, bShared[PVRSRV_MAX_CLIENT_HEAPS];
+	PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+	IMG_UINT32 ui32ClientHeapCount = 0;
+	PVRSRV_PER_PROCESS_DATA	*psPerProc;
+	PVRSRV_ERROR eError;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	gsSyncServicesConnection.ui32Pid = OSGetCurrentProcessIDKM();
+
+	eError = PVRSRVProcessConnect(gsSyncServicesConnection.ui32Pid, 0);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVProcessConnect failed",
+								__func__));
+		goto err_unlock;
+	}
+
+	psPerProc = PVRSRVFindPerProcessData();
+	if (!psPerProc)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVFindPerProcessData failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	eError = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_SGX,
+									   &gsSyncServicesConnection.hDevCookie);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVAcquireDeviceDataKM failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	if (!gsSyncServicesConnection.hDevCookie)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: hDevCookie is NULL", __func__));
+		goto err_disconnect;
+	}
+
+	eError = PVRSRVCreateDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+						psPerProc,
+											&gsSyncServicesConnection.hDevMemContext,
+											&ui32ClientHeapCount,
+											&sHeapInfo[0],
+											&bCreated,
+											&bShared[0]);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVCreateDeviceMemContextKM failed",
+								__func__));
+		goto err_disconnect;
+	}
+
+	if (!gsSyncServicesConnection.hDevMemContext)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: hDevMemContext is NULL", __func__));
+		goto err_disconnect;
+	}
+
+err_unlock:
+	LinuxUnLockMutex(&gPVRSRVLock);
+	return eError;
+
+err_disconnect:
+	PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+	goto err_unlock;
+}
+
+void PVRSyncCloseServices(void)
+{
+	IMG_BOOL bDummy;
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	PVRSRVDestroyDeviceMemContextKM(gsSyncServicesConnection.hDevCookie,
+									gsSyncServicesConnection.hDevMemContext,
+									&bDummy);
+	gsSyncServicesConnection.hDevMemContext = NULL;
+	gsSyncServicesConnection.hDevCookie = NULL;
+
+	PVRSRVProcessDisconnect(gsSyncServicesConnection.ui32Pid);
+	gsSyncServicesConnection.ui32Pid = 0;
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+}*/
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_common.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_common.h
new file mode 100644
index 0000000..cdd9ed0
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_common.h
@@ -0,0 +1,90 @@
+/*************************************************************************/ /*!
+@File           pvr_sync_common.h
+@Title          Kernel sync driver
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Version numbers and strings for PVR Consumer services
+				components.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _PVR_SYNC_COMMON_H
+#define _PVR_SYNC_COMMON_H
+
+#include <linux/seq_file.h>
+#include <linux/version.h>
+
+#if !defined(__KERNEL__) || (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
+#include <linux/sync.h>
+#elif !defined(__KERNEL__) || (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0))
+#include <../drivers/staging/android/sync.h>
+#else
+#include <../drivers/dma-buf/sync_debug.h>
+#endif
+
+#include "pvr_sync_user.h"
+#include "servicesint.h" // PVRSRV_DEVICE_SYNC_OBJECT
+
+/* services4 internal interface */
+
+int PVRSyncDeviceInit(void);
+void PVRSyncDeviceDeInit(void);
+void PVRSyncUpdateAllSyncs(void);
+
+IMG_BOOL
+AddSyncInfoToArray(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+				   IMG_UINT32 ui32SyncPointLimit,
+				   IMG_UINT32 *pui32NumRealSyncs,
+				   PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[]);
+PVRSRV_ERROR
+PVRSyncPatchCCBKickSyncInfos(IMG_HANDLE    ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+		      PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+							 IMG_UINT32 *pui32NumSrcSyncs);
+PVRSRV_ERROR
+PVRSyncPatchTransferSyncInfos(IMG_HANDLE    ahSyncs[SGX_MAX_SRC_SYNCS_TA],
+			  PVRSRV_DEVICE_SYNC_OBJECT asDevSyncs[SGX_MAX_SRC_SYNCS_TA],
+							 IMG_UINT32 *pui32NumSrcSyncs);
+PVRSRV_ERROR
+PVRSyncFencesToSyncInfos(PVRSRV_KERNEL_SYNC_INFO *apsSyncs[],
+						 IMG_UINT32 *pui32NumSyncs,
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC)
+						 struct sync_fence *apsFence[SGX_MAX_SRC_SYNCS_TA]
+#else
+						 struct dma_fence *apsFence[SGX_MAX_SRC_SYNCS_TA]
+#endif
+						 );
+#endif /* _PVR_SYNC_COMMON_H */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_dma_fence.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_dma_fence.c
new file mode 100644
index 0000000..75dc943
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_sync_dma_fence.c
@@ -0,0 +1,812 @@
+/*************************************************************************/ /*!
+@File           pvr_sync2_dma_fence.c
+@Title          Kernel driver for Android's sync mechanism
+@Codingstyle    LinuxKernel
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#include "pvr_sync2.h"
+#include "pvr_sync_common.h"
+#include "pvr_sync_user.h"
+
+#include "pvr_counting_timeline.h"
+
+/* FIXME: Proper interface file? */
+#include <linux/types.h>
+struct sw_sync_create_fence_data {
+	__u32 value;
+	char name[32];
+	__s32 fence;
+};
+#define SW_SYNC_IOC_MAGIC 'W'
+#define SW_SYNC_IOC_CREATE_FENCE \
+	(_IOWR(SW_SYNC_IOC_MAGIC, 0, struct sw_sync_create_fence_data))
+#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/sync_file.h>
+#include <linux/file.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+
+#define DEBUG_OUTPUT 1
+#ifdef DEBUG_OUTPUT
+#define DPF(fmt, ...) PVR_DPF((PVR_DBG_ERROR, "pvr_sync_dma_fence: " fmt "\n", __VA_ARGS__)
+#else
+#define DPF(fmt, ...) do {} while (0)
+#endif
+
+static struct workqueue_struct *gpsWorkQueue;
+
+/* Linux work struct for workqueue. */
+static struct work_struct gsWork;
+
+static const struct file_operations pvr_sync_fops;
+
+static bool is_pvr_timeline(struct file *file)
+{
+	return file->f_op == &pvr_sync_fops;
+}
+
+static struct pvr_sync_timeline *pvr_sync_timeline_fget(int fd)
+{
+	struct file *file = fget(fd);
+
+	if (!file)
+		return NULL;
+
+	if (!is_pvr_timeline(file)) {
+		fput(file);
+		return NULL;
+	}
+
+	return file->private_data;
+}
+
+struct PVR_ALLOC_SYNC_DATA *PVRSyncAllocFDGet(int fd)
+{
+	struct file *file = fget(fd);
+	if (!file)
+		return NULL;
+
+	if (!is_pvr_timeline(file))
+	{
+		fput(file);
+		return NULL;
+	}
+
+	return file->private_data;
+}
+
+/* ioctl and fops handling */
+
+static int pvr_sync_open(struct inode *inode, struct file *file)
+{
+	struct pvr_fence_context *fence_context;
+	struct pvr_sync_timeline *psTimeline;
+	char task_comm[TASK_COMM_LEN];
+	int err = -ENOMEM;
+
+	get_task_comm(task_comm, current);
+
+	timeline = kzalloc(sizeof(*timeline), GFP_KERNEL);
+	if (!timeline)
+		goto err_out;
+
+	strlcpy(timeline->name, task_comm, sizeof(timeline->name));
+
+	PVR_DPF((PVR_DBG_ERROR, "BG: %s: pvr_sync_open ", timeline->name));
+	fence_context =  pvr_fence_context_create(timeline->name);
+	if (!fence_context) {
+		pr_err("pvr_sync2: %s: pvr_fence_context_create failed\n",
+			__func__);
+		goto err_free_timeline;
+	}
+
+	timeline->psSyncInfo = kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if(!timeline->psSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+								"PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		goto err_free_fence;
+	}
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+	eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+								   gsSyncServicesConnection.hDevMemContext,
+								   &timeline->psSyncInfo->psBase);
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate timeline syncinfo",
+								__func__));
+		goto err_free_syncinfo;
+	}
+
+	timeline->fence_context = fence_context;
+	timeline->file = file;
+
+	file->private_data = timeline;
+	err = 0;
+err_out:
+	return err;
+err_free_syncinfo:
+	kfree(timeline->psSyncInfo);
+err_free_fence:
+	pvr_fence_context_destroy(fence_context);
+err_free_timeline:
+	kfree(timeline);
+	goto err_out;
+}
+
+static int pvr_sync_close(struct inode *inode, struct file *file)
+{
+	struct pvr_sync_timeline *timeline = file->private_data;
+
+	if (timeline->sw_timeline)
+	{
+		/* This makes sure any outstanding SW syncs are marked as
+		 * complete at timeline close time. Otherwise it'll leak the
+		 * timeline (as outstanding fences hold a ref) and possibly
+		 * wedge the system is something is waiting on one of those
+		 * fences
+		 */
+		pvr_counting_fence_timeline_force_complete(timeline->sw_timeline);
+		pvr_counting_fence_timeline_put(timeline->sw_timeline);
+	}
+
+	pvr_fence_context_destroy(timeline->fence_context);
+	kfree(timeline);
+
+	return 0;
+}
+
+static long PVRSyncIOCTLCreate(struct pvr_sync_timeline *psTimeline, void __user *pvData)
+{
+	struct PVR_SYNC_KERNEL_SYNC_INFO *psProvidedSyncInfo = NULL;
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+	struct PVR_SYNC_CREATE_IOCTL_DATA sData;
+	int err = -EFAULT, iFd;
+	struct sync_fence *psFence;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0))
+	iFd = get_unused_fd_flags(0);
+#else
+	iFd = get_unused_fd();
+#endif
+	if (iFd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+								__func__, iFd));
+		goto err_out;
+	}
+
+	if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (sData.allocdSyncInfo < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Requested to create a fence from "
+								" an invalid alloc'd fd (%d)", __func__,
+								sData.allocdSyncInfo));
+		goto err_put_fd;
+	}
+
+	psAllocSyncData = PVRSyncAllocFDGet(sData.allocdSyncInfo);
+	if (!psAllocSyncData) {
+		pr_err("pvr_sync2: %s: Failed to open supplied file fd (%d)\n",
+			__func__, new_fence_timeline);
+		err = PVRSRV_ERROR_HANDLE_NOT_FOUND;
+		goto err_put_fd;
+	}
+
+	/* Move the psSyncInfo to the newly created sync, to avoid attempting
+	 * to create multiple syncs from the same allocation.
+	 */
+	psProvidedSyncInfo = psAllocSyncData->psSyncInfo;
+	psAllocSyncData->psSyncInfo = NULL;
+
+	if (psProvidedSyncInfo == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Alloc'd sync info is null - "
+								"possibly already CREATEd?", __func__));
+		fput(psAllocSyncData->psFile);
+		goto err_put_fd;
+	}
+	fput(psAllocSyncData->psFile);
+
+	sData.name[sizeof(sData.name) - 1] = '\0';
+	pvr_fence = pvr_fence_create(timeline->fence_context, sData.name, psProvidedSyncInfo);
+	if (!pvr_fence) {
+		pr_err("pvr_sync2: %s: Failed to create new pvr_fence\n",
+			__func__);
+		err = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto err_put_fd;
+	}
+
+	sync_file = sync_file_create(&pvr_fence->base);
+	if (!sync_file) {
+		pr_err(FILE_NAME ": %s: Failed to create sync_file\n",
+		       __func__);
+		err = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto err_destroy_fence;
+	}
+	fence_put(&pvr_fence->base);
+
+	sData.fence = iFd;
+
+	if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+	{
+		goto err_destroy_fence;
+	}
+
+	if (copy_to_user(pvData, &sData, sizeof(sData)))
+	{
+		goto err_destroy_fence;
+	}
+
+	DPF("C( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X F=%p %s",
+		psProvidedSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psProvidedSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psProvidedSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr,
+		psFence, sData.name);
+
+	fd_install(iFd, sync_file->file);
+	err = 0;
+err_out:
+	return err;
+
+err_destroy_fence:
+	pvr_fence_destroy(pvr_fence);
+err_put_fd:
+	put_unused_fd(iFd);
+	goto err_out;
+}
+
+static long pvr_sync_ioctl_rename(struct pvr_sync_timeline *timeline, void __user *user_data)
+{
+	int err = 0;
+	struct PVR_SYNC_RENAME_IOCTL_DATA data;
+
+	if (!access_ok(VERIFY_READ, user_data, sizeof(data))) {
+		err = -EFAULT;
+		goto err;
+	}
+
+	if (copy_from_user(&data, user_data, sizeof(data))) {
+		err = -EFAULT;
+		goto err;
+	}
+
+	data.szName[sizeof(data.szName) - 1] = '\0';
+	strlcpy(timeline->name, data.name, sizeof(timeline->name));
+
+err:
+	return err;
+}
+
+static long pvr_sync_ioctl_force_sw_only(struct pvr_sync_timeline *timeline,
+	void **private_data)
+{
+	/* Already in SW mode? */
+	if (timeline->sw_timeline)
+		return 0;
+	/* Create a sw_sync timeline with the old GPU timeline's name */
+	timeline->sw_timeline = pvr_counting_fence_timeline_create(
+		timeline->name);
+	if (!timeline->sw_timeline)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static long pvr_sync_ioctl_sw_create_fence(struct pvr_sync_timeline *timeline,
+	void __user *user_data)
+{
+	struct sw_sync_create_fence_data data;
+	struct sync_file *sync_file;
+	int fd = get_unused_fd_flags(0);
+	struct fence *fence;
+	int err = -EFAULT;
+
+	if (fd < 0) {
+		pr_err("pvr_sync2: %s: Failed to find unused fd (%d)\n",
+		       __func__, fd);
+		goto err_out;
+	}
+
+	if (copy_from_user(&data, user_data, sizeof(data))) {
+		pr_err("pvr_sync2: %s: Failed copy from user", __func__);
+		goto err_put_fd;
+	}
+
+	fence = pvr_counting_fence_create(timeline->sw_timeline, data.value);
+	if (!fence) {
+		pr_err("pvr_sync2: %s: Failed to create a sync point (%d)\n",
+		       __func__, fd);
+		err = -ENOMEM;
+		goto err_put_fd;
+	}
+
+	sync_file = sync_file_create(fence);
+	if (!sync_file) {
+		pr_err("pvr_sync2: %s: Failed to create a sync point (%d)\n",
+			__func__, fd);
+		 err = -ENOMEM;
+		goto err_put_fence;
+	}
+
+	data.fence = fd;
+
+	if (copy_to_user(user_data, &data, sizeof(data))) {
+		pr_err("pvr_sync2: %s: Failed copy to user", __func__);
+		goto err_put_fence;
+	}
+
+	fd_install(fd, sync_file->file);
+	err = 0;
+err_out:
+	return err;
+err_put_fence:
+	fence_put(fence);
+err_put_fd:
+	put_unused_fd(fd);
+	goto err_out;
+}
+
+static long pvr_sync_ioctl_sw_inc(struct pvr_sync_timeline *timeline,
+	void __user *user_data)
+{
+	u32 value;
+
+	if (copy_from_user(&value, user_data, sizeof(value)))
+		return -EFAULT;
+
+	pvr_counting_fence_timeline_inc(timeline->sw_timeline, value);
+	return 0;
+}
+
+static long
+PVRSyncIOCTLAlloc(struct pvr_sync_timeline *psTimeline, void __user *pvData)
+{
+	struct PVR_ALLOC_SYNC_DATA *psAllocSyncData;
+	int err = -EFAULT, iFd;
+	struct PVR_SYNC_ALLOC_IOCTL_DATA sData;
+	PVRSRV_SYNC_DATA *psSyncData;
+	struct file *psFile;
+	PVRSRV_ERROR eError;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,2,0))
+	iFd = get_unused_fd_flags(0);
+#else
+	iFd = get_unused_fd();
+#endif
+	if (iFd < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to find unused fd (%d)",
+					__func__, iFd));
+		goto err_out;
+	}
+
+	if (!access_ok(VERIFY_READ, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	if (copy_from_user(&sData, pvData, sizeof(sData)))
+		goto err_put_fd;
+
+	psAllocSyncData = kmalloc(sizeof(struct PVR_ALLOC_SYNC_DATA), GFP_KERNEL);
+	if (!psAllocSyncData)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate PVR_ALLOC_SYNC_DATA",
+								__func__));
+		err = -ENOMEM;
+		goto err_put_fd;
+	}
+
+	psAllocSyncData->psSyncInfo =
+		kmalloc(sizeof(struct PVR_SYNC_KERNEL_SYNC_INFO), GFP_KERNEL);
+	if (!psAllocSyncData->psSyncInfo)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate "
+								"PVR_SYNC_KERNEL_SYNC_INFO", __func__));
+		err = -ENOMEM;
+		goto err_free_alloc_sync_data;
+	}
+
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+	eError = PVRSRVAllocSyncInfoKM(gsSyncServicesConnection.hDevCookie,
+				       gsSyncServicesConnection.hDevMemContext,
+								   &psAllocSyncData->psSyncInfo->psBase);
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to alloc syncinfo (%d)",
+								__func__, eError));
+		err = -ENOMEM;
+		goto err_free_sync_info;
+	}
+
+	psFile = anon_inode_getfile("pvr_fence_alloc",
+								&pvr_sync_fops, psAllocSyncData, 0);
+	if (!psFile)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create anon inode",
+								__func__));
+		err = -ENOMEM;
+		goto err_release_sync_info;
+	}
+
+	sData.fence = iFd;
+
+	/* Check if this timeline looks idle. If there are still TQs running
+	 * on it, userspace shouldn't attempt any kind of power optimization
+	 * (e.g. it must not dummy-process GPU fences).
+	 *
+	 * Determining idleness here is safe because the ALLOC and CREATE
+	 * pvr_sync ioctls must be called under the gralloc module lock, so
+	 * we can't be creating another new fence op while we are still
+	 * processing this one.
+	 *
+	 * Take the bridge lock anyway so we can be sure that we read the
+	 * timeline sync's pending value coherently. The complete value may
+	 * be modified by the GPU, but worse-case we will decide we can't do
+	 * the power optimization and will still be correct.
+	 */
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	psSyncData = psTimeline->psSyncInfo->psBase->psSyncData;
+	if(psSyncData->ui32WriteOpsPending == psSyncData->ui32WriteOpsComplete)
+		sData.bTimelineIdle = IMG_TRUE;
+	else
+		sData.bTimelineIdle = IMG_FALSE;
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+
+	if (!access_ok(VERIFY_WRITE, pvData, sizeof(sData)))
+		goto err_release_file;
+
+	if (copy_to_user(pvData, &sData, sizeof(sData)))
+		goto err_release_file;
+
+	psAllocSyncData->psTimeline = psTimeline;
+	psAllocSyncData->psFile = psFile;
+
+	DPF("A( ): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+		psAllocSyncData->psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+		psAllocSyncData->psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+		psAllocSyncData->psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+	fd_install(iFd, psFile);
+	err = 0;
+err_out:
+	return err;
+err_release_sync_info:
+	PVRSRVReleaseSyncInfoKM(psAllocSyncData->psSyncInfo->psBase);
+err_free_sync_info:
+	kfree(psAllocSyncData->psSyncInfo);
+err_free_alloc_sync_data:
+	kfree(psAllocSyncData);
+err_put_fd:
+	put_unused_fd(iFd);
+	goto err_out;
+err_release_file:
+	fput(psFile);
+	put_unused_fd(iFd);
+	goto err_out;
+}
+
+static long
+pvr_sync_ioctl(struct file *file, unsigned int cmd, unsigned long __user arg)
+{
+	void __user *user_data = (void __user *)arg;
+	long err = -ENOTTY;
+	struct pvr_sync_timeline *pvr = file->private_data;
+	bool is_sw_timeline = pvr->sw_timeline != NULL;
+
+	if (!is_sw_timeline) {
+
+		switch (cmd) {
+		case PVR_SYNC_IOC_CREATE_FENCE:
+			err = PVRSyncIOCTLCreate(pvr, user_data);
+			break;
+		/*case PVR_SYNC_IOC_DEBUG_FENCE:
+			err = PVRSyncIOCTLDebug(pvr, user_data);
+			break;*/
+		case PVR_SYNC_IOC_ALLOC_FENCE:
+			err = PVRSyncIOCTLAlloc(pvr, user_data);
+			break;
+		case PVR_SYNC_IOC_RENAME:
+			err = pvr_sync_ioctl_rename(pvr, user_data);
+			break;
+		case PVR_SYNC_IOC_FORCE_SW_ONLY:
+			err = pvr_sync_ioctl_force_sw_only(pvr, &file->private_data);
+			break;
+		default:
+			err = -ENOTTY;
+		}
+	} else {
+
+		switch (cmd) {
+		case SW_SYNC_IOC_CREATE_FENCE:
+			err = pvr_sync_ioctl_sw_create_fence(pvr, user_data);
+			break;
+		case SW_SYNC_IOC_INC:
+			err = pvr_sync_ioctl_sw_inc(pvr, user_data);
+			break;
+		default:
+			err = -ENOTTY;
+		}
+	}
+
+	return err;
+}
+
+static void PVRSyncWorkQueueFunction(struct work_struct *data)
+{
+	PVRSRV_DEVICE_NODE *psDevNode =
+		(PVRSRV_DEVICE_NODE*)gsSyncServicesConnection.hDevCookie;
+	struct list_head sFreeList, *psEntry, *n;
+	unsigned long flags;
+
+	/* We lock the bridge mutex here for two reasons.
+	 *
+	 * Firstly, the SGXScheduleProcessQueuesKM and PVRSRVReleaseSyncInfoKM
+	 * functions require that they are called under lock. Multiple threads
+	 * into services are not allowed.
+	 *
+	 * Secondly, we need to ensure that when processing the defer-free list,
+	 * the PVRSyncIsSyncInfoInUse() function is called *after* any freed
+	 * sync was attached as a HW dependency (had ROP/ROP2 taken). This is
+	 * because for 'foreign' sync timelines we allocate a new object and
+	 * mark it for deletion immediately. If the 'foreign' sync_pt signals
+	 * before the kick ioctl has completed, we can block it from being
+	 * prematurely freed by holding the bridge mutex.
+	 *
+	 * NOTE: This code relies on the assumption that we can acquire a
+	 * spinlock while a mutex is held and that other users of the spinlock
+	 * do not need to hold the bridge mutex.
+	 */
+	LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE);
+
+	/* A completed SW operation may un-block the GPU */
+	SGXScheduleProcessQueuesKM(psDevNode);
+
+	/* We can't call PVRSRVReleaseSyncInfoKM directly in this loop because
+	 * that will take the mmap mutex. We can't take mutexes while we have
+	 * this list locked with a spinlock. So move all the items we want to
+	 * free to another, local list (no locking required) and process it
+	 * in a second loop.
+	 */
+
+	INIT_LIST_HEAD(&sFreeList);
+	spin_lock_irqsave(&gSyncInfoFreeListLock, flags);
+	list_for_each_safe(psEntry, n, &gSyncInfoFreeList)
+	{
+		struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+			container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		if(!PVRSyncIsSyncInfoInUse(psSyncInfo->psBase))
+			list_move_tail(psEntry, &sFreeList);
+
+	}
+	spin_unlock_irqrestore(&gSyncInfoFreeListLock, flags);
+
+	list_for_each_safe(psEntry, n, &sFreeList)
+	{
+		struct PVR_SYNC_KERNEL_SYNC_INFO *psSyncInfo =
+			container_of(psEntry, struct PVR_SYNC_KERNEL_SYNC_INFO, sHead);
+
+		list_del(psEntry);
+
+		DPF("F(d): WOCVA=0x%.8X ROCVA=0x%.8X RO2CVA=0x%.8X",
+			psSyncInfo->psBase->sWriteOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->psBase->sReadOpsCompleteDevVAddr.uiAddr,
+			psSyncInfo->psBase->sReadOps2CompleteDevVAddr.uiAddr);
+
+		PVRSRVReleaseSyncInfoKM(psSyncInfo->psBase);
+		psSyncInfo->psBase = NULL;
+
+		kfree(psSyncInfo);
+	}
+
+	LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+static const struct file_operations pvr_sync_fops = {
+	.owner          = THIS_MODULE,
+	.open           = pvr_sync_open,
+	.release        = pvr_sync_close,
+	.unlocked_ioctl = pvr_sync_ioctl,
+	.compat_ioctl   = pvr_sync_ioctl,
+};
+
+static struct miscdevice pvr_sync_device = {
+	.minor          = MISC_DYNAMIC_MINOR,
+	.name           = "pvr_sync",
+	.fops           = &pvr_sync_fops,
+};
+
+IMG_INTERNAL
+int PVRSyncDeviceInit(void)
+{
+	int err = -1;
+
+	DPF("%s", __func__);
+
+	if(PVRSyncInitServices() != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise services",
+								__func__));
+		goto err_out;
+	}
+
+	gsSyncServicesConnection.foreign_fence_context = pvr_fence_context_create("foreign_sync");
+	if (!pvr_sync_data.foreign_fence_context) {
+		pr_err("pvr_sync2: %s: Failed to create foreign sync context\n",
+			__func__);
+		error = PVRSRV_ERROR_OUT_OF_MEMORY;
+		goto err_out;
+	}
+
+	gpsWorkQueue = create_freezable_workqueue("pvr_sync_workqueue");
+	if(!gpsWorkQueue)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create pvr_sync workqueue",
+								__func__));
+		goto err_deinit_services;
+	}
+
+	INIT_WORK(&gsWork, PVRSyncWorkQueueFunction);
+
+	err = misc_register(&pvr_sync_device);
+	if(err)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: Failed to register pvr_sync misc "
+								"device (err=%d)", __func__, err));
+		goto err_deinit_services;
+	}
+	error = PVRSRV_OK;
+
+err_out:
+	return err;
+err_deinit_services:
+	pvr_fence_context_destroy(pvr_sync_data.foreign_fence_context);
+	PVRSyncCloseServices();
+	goto err_out;
+}
+
+void PVRSyncDeviceDeInit(void)
+{
+	DPF("%s", __func__);
+	misc_deregister(&pvr_sync_device);
+	pvr_fence_context_destroy(pvr_sync_data.foreign_fence_context);
+	PVRSyncCloseServices();
+}
+
+struct pvr_counting_fence_timeline *pvr_sync_get_sw_timeline(int fd)
+{
+	struct pvr_sync_timeline *timeline;
+	struct pvr_counting_fence_timeline *sw_timeline = NULL;
+
+	timeline = pvr_sync_timeline_fget(fd);
+	if (!timeline)
+		return NULL;
+
+	sw_timeline = pvr_counting_fence_timeline_get(timeline->sw_timeline);
+
+	pvr_sync_timeline_fput(timeline);
+	return sw_timeline;
+}
+
+IMG_BOOL
+ExpandAndDeDuplicateFenceSyncs(IMG_UINT32 ui32NumSyncs,
+							   IMG_HANDLE aiFenceFds[],
+							   IMG_UINT32 ui32SyncPointLimit,
+							   struct sync_fence *apsFence[],
+							   IMG_UINT32 *pui32NumRealSyncs,
+							   PVRSRV_KERNEL_SYNC_INFO *apsSyncInfo[])
+{
+	IMG_UINT32 i, j, ui32FenceIndex = 0;
+	IMG_BOOL bRet = IMG_TRUE;
+	struct sync_pt *psPt;
+
+	*pui32NumRealSyncs = 0;
+
+	for(i = 0; i < ui32NumSyncs; i++)
+	{
+		PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+		struct pvr_fence *fence;
+
+		/* Skip any invalid fence file descriptors without error */
+		if((IMG_INT32)aiFenceFds[i] < 0)
+			continue;
+
+		/* By converting a file descriptor to a struct sync_fence, we are
+		 * taking a reference on the fence. We don't want the fence to go
+		 * away until we have submitted the command, even if it signals
+		 * before we dispatch the command, or the timeline(s) are destroyed.
+		 *
+		 * This reference should be released by the caller of this function
+		 * once hardware operations have been scheduled on the GPU sync_pts
+		 * participating in this fence. When our MISR is scheduled, the
+		 * defer-free list will be processed, cleaning up the SYNCINFO.
+		 *
+		 * Note that this reference *isn't* enough for non-GPU sync_pts.
+		 * We'll take another reference on the fence for those operations
+		 * later (the life-cycle requirements there are totally different).
+		 *
+		 * Fence lookup may fail here if the fd became invalid since it was
+		 * patched in userspace. That's really a userspace driver bug, so
+		 * just fail here instead of not synchronizing.
+		 */
+		apsFence[ui32FenceIndex] = sync_file_get_fence((IMG_INT32)aiFenceFds[i]);
+		if(!apsFence[ui32FenceIndex])
+		{
+			PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get fence from fd=%d",
+									__func__, (IMG_SIZE_T)aiFenceFds[i]));
+			bRet = IMG_FALSE;
+			goto err_out;
+		}
+
+		/* If this fence has any points from foreign timelines, we need to
+		 * allocate a 'shadow' SYNCINFO and update it in software ourselves,
+		 * so the ukernel can test the readiness of the dependency.
+		 *
+		 * It's tempting to just handle all fences like this (since most of
+		 * the time they *will* be merged with sw_sync) but such 'shadow'
+		 * syncs are slower. This is because we need to wait for the MISR to
+		 * schedule to update the GPU part of the fence (normally the ukernel
+		 * would be able to make the update directly).
+		 */
+		fence = to_pvr_fence(apsFence[ui32FenceIndex]);
+		if(!fence)
+		{
+			fence = pvr_fence_create_from_fence(gsSyncServicesConnection.foreign_fence_context, apsFence[ui32FenceIndex], "foreign");
+			if(fence)
+			{
+				if(!AddSyncInfoToArray(fence->psSyncData->psSyncInfo, ui32SyncPointLimit,
+									   pui32NumRealSyncs, apsSyncInfo))
+				{
+					/* Soft-fail. Stop synchronizing. */
+					goto err_out;
+				}
+			}
+		}
+		else
+		{
+			/* Walk the current list of points and make sure this isn't a
+			 * duplicate. Duplicates will deadlock.
+			 */
+			for(j = 0; j < *pui32NumRealSyncs; j++)
+			{
+				/* The point is from a different timeline so we must use it */
+				if(!PVRSyncIsDuplicate(apsSyncInfo[j], fence->psSyncData->psSyncInfo))
+					continue;
+
+				/* There's no need to bump the real sync count as we either
+				 * ignored the duplicate or replaced an previously counted
+				 * entry.
+				 */
+				break;
+			}
+			if(j == *pui32NumRealSyncs)
+			{
+				/* It's not a duplicate; moving on.. */
+				if(!AddSyncInfoToArray(psSyncInfo, ui32SyncPointLimit,
+									   pui32NumRealSyncs, apsSyncInfo))
+					goto err_out;
+			}
+		}
+		ui32FenceIndex++;
+	}
+
+err_out:
+	return bRet;
+}
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h
new file mode 100644
index 0000000..10e289b
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_uaccess.h
@@ -0,0 +1,89 @@
+/*************************************************************************/ /*!
+@Title          Utility functions for user space access
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __PVR_UACCESS_H__
+#define __PVR_UACCESS_H__
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#endif
+
+#include <linux/uaccess.h>
+#include <asm/uaccess.h>
+
+static inline unsigned long pvr_copy_to_user(void __user *pvTo, const void *pvFrom, unsigned long ulBytes)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+    if (access_ok(VERIFY_WRITE, pvTo, ulBytes))
+    {
+	return __copy_to_user(pvTo, pvFrom, ulBytes);
+    }
+    return ulBytes;
+#else
+    return copy_to_user(pvTo, pvFrom, ulBytes);
+#endif
+}
+
+static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+    /*
+     * The compile time correctness checking introduced for copy_from_user in
+     * Linux 2.6.33 isn't fully comaptible with our usage of the function.
+     */
+    if (access_ok(VERIFY_READ, pvFrom, ulBytes))
+    {
+	return __copy_from_user(pvTo, pvFrom, ulBytes);
+    }
+    return ulBytes;
+#else
+    return copy_from_user(pvTo, pvFrom, ulBytes);
+#endif
+}
+
+#define	pvr_put_user	put_user
+#define	pvr_get_user	get_user
+
+#endif /* __PVR_UACCESS_H__ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvrsrv_sync_server.h b/drivers/gpu/pvr/services4/srvkm/env/linux/pvrsrv_sync_server.h
new file mode 100644
index 0000000..277d4b9
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvrsrv_sync_server.h
@@ -0,0 +1,29 @@
+#ifndef _PVRSRV_SYNC_SERVER_H_
+#define _PVRSRV_SYNC_SERVER_H_
+
+#include "img_types.h"
+
+#define SYNC_SW_TIMELINE_MAX_LENGTH 32
+#define SYNC_SW_FENCE_MAX_LENGTH 32
+
+/*****************************************************************************/
+/*                                                                           */
+/*                      SW TIMELINE SPECIFIC FUNCTIONS                       */
+/*                                                                           */
+/*****************************************************************************/
+
+struct dma_fence* SyncSWTimelineFenceCreateKM(IMG_INT32 iSWTimeline,
+					IMG_UINT32 ui32NextSyncPtVal,
+					const IMG_CHAR *pszFenceName);
+
+PVRSRV_ERROR SyncSWTimelineAdvanceKM(IMG_PVOID pvSWTimelineObj);
+
+PVRSRV_ERROR SyncSWTimelineReleaseKM(IMG_PVOID pvSWTimelineObj);
+
+PVRSRV_ERROR SyncSWTimelineFenceReleaseKM(IMG_PVOID i32SWFenceObj);
+
+PVRSRV_ERROR SyncSWGetTimelineObj(IMG_INT32 iSWTimeline, IMG_PVOID *ppvSWTimelineObj);
+
+PVRSRV_ERROR SyncSWGetFenceObj(IMG_INT32 iSWFence, IMG_PVOID *ppvSWFenceObj);
+
+#endif /* _PVRSRV_SYNC_SERVER_H_ */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.c b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.c
new file mode 100644
index 0000000..f09eba4
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.c
@@ -0,0 +1,376 @@
+/*************************************************************************/ /*!
+@Title          Systrace related functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "systrace.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/gpu.h>
+
+#include <linux/debugfs.h>
+#include <linux/sched/clock.h>
+#include <linux/fs.h>
+
+#include "img_types.h"
+
+#if defined(EUR_CR_TIMER)
+
+/*Kernel debugfs variables*/
+#define PVRSRV_SYSTRACE_TIMEINDEX_LIMIT 32
+static bool capture_hwperfdata;
+static struct dentry *pvrdir_ret;
+
+static PVRSRV_SYSTRACE_ERROR CreateJob(PVRSRV_SYSTRACE_DATA *psSystraceData, IMG_UINT32 ui32PID, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData)
+{
+	PVRSRV_SYSTRACE_CONTEXT *psContext = NULL;
+	PVRSRV_SYSTRACE_JOB 	*psJob = NULL;
+	IMG_UINT32 i = 0;
+	
+	if(psSystraceData == NULL)
+		return PVRSRV_SYSTRACE_NOT_INITIALISED;
+	
+	/*Look for the PID in the context CB*/
+	for(i = 0; i < 8; ++i)
+	{
+		if(psSystraceData->asSystraceContext[i].ui32PID == ui32PID)
+		{
+			psContext = &(psSystraceData->asSystraceContext[i]);
+			break;
+		}
+	}
+
+	/*If we find it lets check its jobs, otherwise we create it*/
+	if(psContext == NULL)
+	{
+		psSystraceData->ui32Index = (psSystraceData->ui32Index+1)%8;
+		
+		psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32CtxID = psSystraceData->ui32CurrentCtxID;
+		++psSystraceData->ui32CurrentCtxID;
+		psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32PID = ui32PID;
+		psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32Start = 0;
+		psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32End = 0;
+		psSystraceData->asSystraceContext[psSystraceData->ui32Index].ui32CurrentJobID = 0;
+		
+		psContext = &(psSystraceData->asSystraceContext[psSystraceData->ui32Index]);
+	}
+
+	/*This is just done during the first kick so it must not be in the job list*/
+	/*JobID not found, we create it*/
+	psJob = &(psContext->asJobs[psContext->ui32End]);
+	psJob->ui32JobID = psContext->ui32CurrentJobID;
+	++psContext->ui32CurrentJobID;
+	
+	psJob->ui32FrameNum = ui32FrameNum;
+	psJob->ui32RTData = ui32RTData;
+	/*Advance the CB*/
+	psContext->ui32End = (psContext->ui32End + 1)%16;
+	if(psContext->ui32End == psContext->ui32Start)
+		psContext->ui32Start = (psContext->ui32Start + 1)%16;
+
+	return PVRSRV_SYSTRACE_OK;
+}
+
+static PVRSRV_SYSTRACE_ERROR GetCtxAndJobID(PVRSRV_SYSTRACE_DATA *psSystraceData, IMG_UINT32 ui32PID, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData, 
+					IMG_UINT32 *pui32CtxID, IMG_UINT32 *pui32JobID)
+{
+	PVRSRV_SYSTRACE_CONTEXT *psContext = NULL;
+	//PVRSRV_SYSTRACE_JOB 	*psJob = NULL;
+	IMG_UINT32 i = 0;
+	
+	if(psSystraceData == NULL)
+		return PVRSRV_SYSTRACE_NOT_INITIALISED;
+	
+	/*Look for the PID in the context CB*/
+	for(i = 0; i < 8; ++i)
+	{
+		if(psSystraceData->asSystraceContext[i].ui32PID == ui32PID)
+		{
+			psContext = &(psSystraceData->asSystraceContext[i]);
+			break;
+		}
+	}
+	/*If we find it lets check its jobs, otherwise we create it*/
+	if(psContext == NULL)
+	{
+		/*Don't create anything here*/
+		return PVRSRV_SYSTRACE_JOB_NOT_FOUND;
+	}
+	/*Look for the JobID in the jobs CB otherwise create it and return ID*/
+	for(i = 0; i < 16; ++i)
+	{
+		if((psContext->asJobs[i].ui32FrameNum == ui32FrameNum) &&
+			(psContext->asJobs[i].ui32RTData == ui32RTData))
+		{
+			*pui32CtxID = psContext->ui32CtxID;
+			*pui32JobID = psContext->asJobs[i].ui32JobID;
+			return PVRSRV_SYSTRACE_OK;
+		}
+	}
+	/*Not found*/
+	return PVRSRV_SYSTRACE_JOB_NOT_FOUND;
+}
+
+void SystraceCreateFS(void)
+{
+	struct dentry *capture_sgx_hwperfdata_ret;
+	
+	pvrdir_ret = debugfs_create_dir("pvr", NULL);
+	capture_sgx_hwperfdata_ret = debugfs_create_bool("gpu_tracing_on", S_IFREG | S_IRUGO | S_IWUSR, pvrdir_ret, &capture_hwperfdata);
+}
+
+void SystraceDestroyFS(void)
+{
+	debugfs_remove_recursive(pvrdir_ret);
+}
+
+IMG_BOOL SystraceIsCapturingHWData(void)
+{
+	return capture_hwperfdata;
+}
+
+void SystraceTAKick(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData, IMG_BOOL bIsFirstKick)
+{
+	IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+	IMG_UINT32 ui32JobID = 0;
+	IMG_UINT32 ui32CtxID = 0;
+	PVRSRV_SYSTRACE_ERROR eError = PVRSRV_SYSTRACE_OK;
+	
+	if(psDevInfo->bSystraceInitialised)
+	{
+		if(bIsFirstKick)
+		{
+			eError = CreateJob(psDevInfo->psSystraceData, ui32PID, ui32FrameNum, ui32RTData);
+			if(eError != PVRSRV_SYSTRACE_OK)
+			{
+				PVR_DPF((PVR_DBG_WARNING,"Systrace: Error creating a Job"));
+			}
+		}
+		
+		eError = GetCtxAndJobID(psDevInfo->psSystraceData, ui32PID, ui32FrameNum, ui32RTData, &ui32CtxID, &ui32JobID);
+		
+		if(eError != PVRSRV_SYSTRACE_OK)
+		{
+			PVR_DPF((PVR_DBG_WARNING,"Systrace: Job not found"));
+		}
+		
+		trace_gpu_job_enqueue(ui32CtxID, ui32JobID, "TA");
+	}
+}
+
+void SystraceInitializeTimeCorr(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+	IMG_UINT32 ui32CurrentIndex = psDevInfo->psSystraceData->ui32TimeCorrIndex;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+	
+	if(psSGXHostCtl->ui32TicksAtPowerUp != 0)
+	{
+		IMG_UINT32 ui32Clocksx16Difference = 0;
+		IMG_UINT64 ui64TimeDifference = 0;
+		IMG_UINT64 ui64HostTime = 0;
+		IMG_UINT32 ui32SGXClocksx16 = 0;
+		IMG_UINT32 ui32ClockMultiplier = 0;
+
+		ui64HostTime = sched_clock();
+		ui32SGXClocksx16 = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_TIMER,0));
+
+		if(ui32SGXClocksx16 > psSGXHostCtl->ui32TicksAtPowerUp)
+		{
+		
+			/* Get the ui32ClockMultipliertiplier per 1us*/
+			ui32ClockMultiplier = (psDevInfo->ui32CoreClockSpeed) / (1000*1000);
+
+			ui32Clocksx16Difference = ui32SGXClocksx16 - psSGXHostCtl->ui32TicksAtPowerUp;
+			
+			/* Multiply it by 16 and 1000 to convert from us to ns
+			 * Breaking it in two steps to avoid overflow */
+			ui64TimeDifference = (16 * ui32Clocksx16Difference) / ui32ClockMultiplier;
+			ui64TimeDifference = (unsigned long long)1000 * ui64TimeDifference;
+
+			psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui64HostTime = ui64HostTime - ui64TimeDifference;
+			psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui32SGXClocksx16 = psSGXHostCtl->ui32TicksAtPowerUp;
+
+			ui32CurrentIndex =  (ui32CurrentIndex + 1) % PVRSRV_SYSTRACE_TIMEINDEX_LIMIT;
+		}
+	}
+
+	/* Initialize with current GPU ticks and host clock */
+	psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui64HostTime = sched_clock();
+	psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui32SGXClocksx16 = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_TIMER,0));
+
+	psDevInfo->psSystraceData->ui32TimeCorrIndex = ui32CurrentIndex;
+	psSGXHostCtl->ui32SystraceIndex = psDevInfo->psSystraceData->ui32TimeCorrIndex;
+	psSGXHostCtl->ui32TicksAtPowerUp = 0;
+}
+
+void SystraceUpdateTimeCorr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32ClockMultiplier)
+{
+	IMG_UINT32 ui32LastIndex = psDevInfo->psSystraceData->ui32TimeCorrIndex;
+	IMG_UINT32 ui32CurrentIndex = 0;
+	SGXMKIF_HOST_CTL	*psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+	if(psSGXHostCtl->ui32SGXPoweredOn)
+	{
+		if((psDevInfo->psSystraceData->bLastPowerDown == IMG_TRUE) && (psSGXHostCtl->ui32TicksAtPowerUp != 0))
+		{
+			IMG_UINT32 ui32Clocksx16Difference = 0;
+			IMG_UINT64 ui64TimeDifference = 0;
+			IMG_UINT64 ui64HostTime = 0;
+			IMG_UINT32 ui32SGXClocksx16 = 0;
+
+			ui64HostTime = sched_clock();
+			ui32SGXClocksx16 = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_TIMER,0));
+
+			if(ui32SGXClocksx16 > psSGXHostCtl->ui32TicksAtPowerUp)
+			{
+				ui32CurrentIndex =  ui32LastIndex;
+
+				ui32Clocksx16Difference = ui32SGXClocksx16 - psSGXHostCtl->ui32TicksAtPowerUp;
+			
+				/* Multiply it by 16 and 1000 to convert from us to ns
+				 * Breaking it in two steps to avoid overflow */
+				ui64TimeDifference = (16 * ui32Clocksx16Difference) / ui32ClockMultiplier;
+				ui64TimeDifference = (unsigned long long)1000 * ui64TimeDifference;
+			
+				psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui64HostTime = ui64HostTime - ui64TimeDifference;
+				psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui32SGXClocksx16 = psSGXHostCtl->ui32TicksAtPowerUp;
+			}
+		}
+		ui32CurrentIndex =  (ui32LastIndex + 1) % PVRSRV_SYSTRACE_TIMEINDEX_LIMIT;
+
+		psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui64HostTime = sched_clock();
+		psDevInfo->psSystraceData->asTimeCorrArray[ui32CurrentIndex].ui32SGXClocksx16 = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_TIMER,0));
+		
+		psDevInfo->psSystraceData->ui32TimeCorrIndex = ui32CurrentIndex ;
+		psSGXHostCtl->ui32SystraceIndex = psDevInfo->psSystraceData->ui32TimeCorrIndex;
+		psSGXHostCtl->ui32TicksAtPowerUp = 0;
+		psDevInfo->psSystraceData->bLastPowerDown = IMG_FALSE;
+	}
+	else
+	{
+		if(psDevInfo->psSystraceData->bLastPowerDown != IMG_TRUE)
+		{
+			/* Device is powered down first time from powered up state,
+			 * pre-increment index so it will be used for initial packets generated before first MISR after power up */
+
+			ui32CurrentIndex =  (ui32LastIndex + 1) % PVRSRV_SYSTRACE_TIMEINDEX_LIMIT;
+			psDevInfo->psSystraceData->ui32TimeCorrIndex = ui32CurrentIndex ;
+			psSGXHostCtl->ui32SystraceIndex = psDevInfo->psSystraceData->ui32TimeCorrIndex;
+		}
+		psDevInfo->psSystraceData->bLastPowerDown = IMG_TRUE;
+		psSGXHostCtl->ui32TicksAtPowerUp = 0;
+		PVR_DPF((PVR_DBG_WARNING, "Systrace: Device PoweredOff, skipping update!"));
+	}
+}
+
+void SystraceHWPerfPackets(PVRSRV_SGXDEV_INFO *psDevInfo, PVRSRV_SGX_HWPERF_CB_ENTRY* psSGXHWPerf, IMG_UINT32 ui32DataCount, IMG_UINT32 ui32SgxClockspeed)
+{
+	IMG_UINT32 ui32PID, ui32FrameNo, ui32EvtType, ui32RTData, ui32Clocksx16Difference, ui32ClockMultiplier, ui32SystraceIndex;
+	
+	IMG_UINT32 ui32SgxClocksx16 = 0;
+	IMG_UINT32 i = 0;
+	IMG_UINT64 ui64TimeDifference = 0;
+	IMG_UINT64 ui64PacketTimeStamp = 0;
+	
+	IMG_UINT32 ui32JobID = 0;
+	IMG_UINT32 ui32CtxID = 0;
+
+	/* Get the ui32ClockMultipliertiplier per 1us*/
+	ui32ClockMultiplier = (ui32SgxClockspeed)/(1000*1000);
+
+	SystraceUpdateTimeCorr(psDevInfo, ui32ClockMultiplier);
+
+	for(i = 0; i < ui32DataCount; ++i)
+	{
+		ui32SgxClocksx16 = psSGXHWPerf[i].ui32Clocksx16;
+		ui32EvtType = psSGXHWPerf[i].ui32Type;
+		ui32FrameNo = psSGXHWPerf[i].ui32FrameNo;
+		ui32PID = psSGXHWPerf[i].ui32PID;
+		ui32RTData = psSGXHWPerf[i].ui32RTData;
+		ui32SystraceIndex = psSGXHWPerf[i].ui32SystraceIndex;
+
+		if ((ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_TA_START) ||
+			(ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_TA_END) ||
+			(ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_3D_START) ||
+			(ui32EvtType == PVRSRV_SGX_HWPERF_TYPE_3D_END))
+		{
+			/*Get the JobID*/
+			GetCtxAndJobID(psDevInfo->psSystraceData, ui32PID, ui32FrameNo, ui32RTData, &ui32CtxID, &ui32JobID);
+			if (ui32SgxClocksx16 < psDevInfo->psSystraceData->asTimeCorrArray[ui32SystraceIndex].ui32SGXClocksx16)
+			{
+				PVR_DPF((PVR_DBG_ERROR, "Systrace: Dropping current HW packet!"));
+				continue;
+			}
+
+			ui32Clocksx16Difference = (ui32SgxClocksx16 - psDevInfo->psSystraceData->asTimeCorrArray[ui32SystraceIndex].ui32SGXClocksx16);
+
+			/* Multiply it by 16 and 1000 to convert from us to ns
+			 * Breaking it in two steps to avoid overflow */
+			ui64TimeDifference = (16 * ui32Clocksx16Difference) / ui32ClockMultiplier;
+			ui64TimeDifference = (unsigned long long)1000 * ui64TimeDifference;
+
+			/* Add the time diff to the last time-stamp, in nanoseconds*/
+			ui64PacketTimeStamp = (unsigned long long) psDevInfo->psSystraceData->asTimeCorrArray[ui32SystraceIndex].ui64HostTime \
+							+ (unsigned long long)ui64TimeDifference;
+			
+			switch(ui32EvtType)
+			{
+				case PVRSRV_SGX_HWPERF_TYPE_TA_START:
+					trace_gpu_sched_switch("TA", ui64PacketTimeStamp, ui32CtxID, ui32FrameNo, ui32JobID);
+					break;
+				
+				case PVRSRV_SGX_HWPERF_TYPE_TA_END:
+					trace_gpu_sched_switch("TA", ui64PacketTimeStamp, 0, ui32FrameNo, ui32JobID);
+					break;
+				
+				case PVRSRV_SGX_HWPERF_TYPE_3D_START:
+					trace_gpu_sched_switch("3D", ui64PacketTimeStamp, ui32CtxID, ui32FrameNo, ui32JobID);
+					break;
+				
+				case PVRSRV_SGX_HWPERF_TYPE_3D_END:
+					trace_gpu_sched_switch("3D", ui64PacketTimeStamp, 0, ui32FrameNo, ui32JobID);
+					break;
+				
+				default:
+				break;
+			}
+		}
+	}
+}
+#endif /* #if defined(EUR_CR_TIMER) */
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.h b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.h
new file mode 100644
index 0000000..71c80dc
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/env/linux/systrace.h
@@ -0,0 +1,70 @@
+/*************************************************************************/ /*!
+@Title          Systrace related functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SYSTRACE_
+#define _SYSTRACE_
+
+#include "img_defs.h"
+#include "img_types.h"
+
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+
+typedef enum 
+{
+	PVRSRV_SYSTRACE_OK = 0x00,
+	PVRSRV_SYSTRACE_NOT_INITIALISED,
+	PVRSRV_SYSTRACE_JOB_NOT_FOUND
+} PVRSRV_SYSTRACE_ERROR;
+
+
+void SystraceHWPerfPackets(PVRSRV_SGXDEV_INFO *psDevInfo, PVRSRV_SGX_HWPERF_CB_ENTRY* psSGXHWPerf, IMG_UINT32 ui32DataCount, IMG_UINT32 ui32SgxClockspeed);
+void SystraceTAKick(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FrameNum, IMG_UINT32 ui32RTData, IMG_BOOL bIsFirstKick);
+void SystraceInitializeTimeCorr(PVRSRV_SGXDEV_INFO *psDevInfo);
+void SystraceUpdateTimeCorr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32ClockMultiplier);
+
+void SystraceCreateFS(void);
+void SystraceDestroyFS(void);
+IMG_BOOL SystraceIsCapturingHWData(void);
+
+#endif /* _SYSTRACE_ */
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/mnemedefs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/mnemedefs.h
new file mode 100644
index 0000000..83a65f5
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/mnemedefs.h
@@ -0,0 +1,117 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for MNEME.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _MNEMEDEFS_KM_H_
+#define _MNEMEDEFS_KM_H_
+
+/* Register MNE_CR_CTRL */
+#define MNE_CR_CTRL                         0x0D00
+#define MNE_CR_CTRL_BYP_CC_N_MASK           0x00010000U
+#define MNE_CR_CTRL_BYP_CC_N_SHIFT          16
+#define MNE_CR_CTRL_BYP_CC_N_SIGNED         0
+#define MNE_CR_CTRL_BYP_CC_MASK             0x00008000U
+#define MNE_CR_CTRL_BYP_CC_SHIFT            15
+#define MNE_CR_CTRL_BYP_CC_SIGNED           0
+#define MNE_CR_CTRL_USE_INVAL_REQ_MASK      0x00007800U
+#define MNE_CR_CTRL_USE_INVAL_REQ_SHIFT     11
+#define MNE_CR_CTRL_USE_INVAL_REQ_SIGNED    0
+#define MNE_CR_CTRL_BYPASS_ALL_MASK         0x00000400U
+#define MNE_CR_CTRL_BYPASS_ALL_SHIFT        10
+#define MNE_CR_CTRL_BYPASS_ALL_SIGNED       0
+#define MNE_CR_CTRL_BYPASS_MASK             0x000003E0U
+#define MNE_CR_CTRL_BYPASS_SHIFT            5
+#define MNE_CR_CTRL_BYPASS_SIGNED           0
+#define MNE_CR_CTRL_PAUSE_MASK              0x00000010U
+#define MNE_CR_CTRL_PAUSE_SHIFT             4
+#define MNE_CR_CTRL_PAUSE_SIGNED            0
+/* Register MNE_CR_USE_INVAL */
+#define MNE_CR_USE_INVAL                    0x0D04
+#define MNE_CR_USE_INVAL_ADDR_MASK          0xFFFFFFFFU
+#define MNE_CR_USE_INVAL_ADDR_SHIFT         0
+#define MNE_CR_USE_INVAL_ADDR_SIGNED        0
+/* Register MNE_CR_STAT */
+#define MNE_CR_STAT                         0x0D08
+#define MNE_CR_STAT_PAUSED_MASK             0x00000400U
+#define MNE_CR_STAT_PAUSED_SHIFT            10
+#define MNE_CR_STAT_PAUSED_SIGNED           0
+#define MNE_CR_STAT_READS_MASK              0x000003FFU
+#define MNE_CR_STAT_READS_SHIFT             0
+#define MNE_CR_STAT_READS_SIGNED            0
+/* Register MNE_CR_STAT_STATS */
+#define MNE_CR_STAT_STATS                   0x0D0C
+#define MNE_CR_STAT_STATS_RST_MASK          0x000FFFF0U
+#define MNE_CR_STAT_STATS_RST_SHIFT         4
+#define MNE_CR_STAT_STATS_RST_SIGNED        0
+#define MNE_CR_STAT_STATS_SEL_MASK          0x0000000FU
+#define MNE_CR_STAT_STATS_SEL_SHIFT         0
+#define MNE_CR_STAT_STATS_SEL_SIGNED        0
+/* Register MNE_CR_STAT_STATS_OUT */
+#define MNE_CR_STAT_STATS_OUT               0x0D10
+#define MNE_CR_STAT_STATS_OUT_VALUE_MASK    0xFFFFFFFFU
+#define MNE_CR_STAT_STATS_OUT_VALUE_SHIFT   0
+#define MNE_CR_STAT_STATS_OUT_VALUE_SIGNED  0
+/* Register MNE_CR_EVENT_STATUS */
+#define MNE_CR_EVENT_STATUS                 0x0D14
+#define MNE_CR_EVENT_STATUS_INVAL_MASK      0x00000001U
+#define MNE_CR_EVENT_STATUS_INVAL_SHIFT     0
+#define MNE_CR_EVENT_STATUS_INVAL_SIGNED    0
+/* Register MNE_CR_EVENT_CLEAR */
+#define MNE_CR_EVENT_CLEAR                  0x0D18
+#define MNE_CR_EVENT_CLEAR_INVAL_MASK       0x00000001U
+#define MNE_CR_EVENT_CLEAR_INVAL_SHIFT      0
+#define MNE_CR_EVENT_CLEAR_INVAL_SIGNED     0
+/* Register MNE_CR_CTRL_INVAL */
+#define MNE_CR_CTRL_INVAL                   0x0D20
+#define MNE_CR_CTRL_INVAL_PREQ_PDS_MASK     0x00000008U
+#define MNE_CR_CTRL_INVAL_PREQ_PDS_SHIFT    3
+#define MNE_CR_CTRL_INVAL_PREQ_PDS_SIGNED   0
+#define MNE_CR_CTRL_INVAL_PREQ_USEC_MASK    0x00000004U
+#define MNE_CR_CTRL_INVAL_PREQ_USEC_SHIFT   2
+#define MNE_CR_CTRL_INVAL_PREQ_USEC_SIGNED  0
+#define MNE_CR_CTRL_INVAL_PREQ_CACHE_MASK   0x00000002U
+#define MNE_CR_CTRL_INVAL_PREQ_CACHE_SHIFT  1
+#define MNE_CR_CTRL_INVAL_PREQ_CACHE_SIGNED 0
+#define MNE_CR_CTRL_INVAL_ALL_MASK          0x00000001U
+#define MNE_CR_CTRL_INVAL_ALL_SHIFT         0
+#define MNE_CR_CTRL_INVAL_ALL_SIGNED        0
+
+#endif /* _MNEMEDEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/ocpdefs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/ocpdefs.h
new file mode 100644
index 0000000..07a6412
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/ocpdefs.h
@@ -0,0 +1,308 @@
+/*************************************************************************/ /*!
+@Title          OCP HW definitions.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _OCPDEFS_H_
+#define _OCPDEFS_H_
+
+/* Register EUR_CR_OCP_REVISION */
+#define EUR_CR_OCP_REVISION                 0xFE00
+#define EUR_CR_OCP_REVISION_REV_MASK        0xFFFFFFFFUL
+#define EUR_CR_OCP_REVISION_REV_SHIFT       0
+#define EUR_CR_OCP_REVISION_REV_SIGNED      0
+
+/* Register EUR_CR_OCP_HWINFO */
+#define EUR_CR_OCP_HWINFO                   0xFE04
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_MASK 0x00000003UL
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SHIFT 0
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SIGNED 0
+
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_MASK 0x00000004UL
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SHIFT 2
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SIGNED 0
+
+/* Register EUR_CR_OCP_SYSCONFIG */
+#define EUR_CR_OCP_SYSCONFIG                0xFE10
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_MASK 0x0000000CUL
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SHIFT 2
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SIGNED 0
+
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_MASK 0x00000030UL
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SHIFT 4
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_0 */
+#define EUR_CR_OCP_IRQSTATUS_RAW_0          0xFE24
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_1 */
+#define EUR_CR_OCP_IRQSTATUS_RAW_1          0xFE28
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_2 */
+#define EUR_CR_OCP_IRQSTATUS_RAW_2          0xFE2C
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_0 */
+#define EUR_CR_OCP_IRQSTATUS_0              0xFE30
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_MASK    0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_SHIFT   0
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_SIGNED  0
+
+/* Register EUR_CR_OCP_IRQSTATUS_1 */
+#define EUR_CR_OCP_IRQSTATUS_1              0xFE34
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_MASK  0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_2 */
+#define EUR_CR_OCP_IRQSTATUS_2              0xFE38
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_SET_0 */
+#define EUR_CR_OCP_IRQENABLE_SET_0          0xFE3C
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_SET_1 */
+#define EUR_CR_OCP_IRQENABLE_SET_1          0xFE40
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_SET_2 */
+#define EUR_CR_OCP_IRQENABLE_SET_2          0xFE44
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_CLR_0 */
+#define EUR_CR_OCP_IRQENABLE_CLR_0          0xFE48
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_CLR_1 */
+#define EUR_CR_OCP_IRQENABLE_CLR_1          0xFE4C
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_CLR_2 */
+#define EUR_CR_OCP_IRQENABLE_CLR_2          0xFE50
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_PAGE_CONFIG */
+#define EUR_CR_OCP_PAGE_CONFIG              0xFF00
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_MASK 0x00000001UL
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SHIFT 0
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SIGNED 0
+
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_MASK 0x00000004UL
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_SHIFT 2
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_SIGNED 0
+
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_MASK    0x00000018UL
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SHIFT   3
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SIGNED  0
+
+/* Register EUR_CR_OCP_INTERRUPT_EVENT */
+#define EUR_CR_OCP_INTERRUPT_EVENT          0xFF04
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_MASK 0x00000001UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SHIFT 0
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_MASK 0x00000002UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_SHIFT 1
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_MASK 0x00000004UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_SHIFT 2
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_MASK 0x00000008UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_SHIFT 3
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_MASK 0x00000010UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_SHIFT 4
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_MASK 0x00000020UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_SHIFT 5
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_MASK 0x00000100UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_SHIFT 8
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_MASK 0x00000200UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_SHIFT 9
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_MASK 0x00000400UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SHIFT 10
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SIGNED 0
+
+/* Register EUR_CR_OCP_DEBUG_CONFIG */
+#define EUR_CR_OCP_DEBUG_CONFIG             0xFF08
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_MASK 0x00000003UL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SHIFT 0
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_MASK 0x0000000CUL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_SHIFT 2
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_MASK 0x00000010UL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_SHIFT 4
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_MASK 0x00000020UL
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_SHIFT 5
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_MASK 0x80000000UL
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SHIFT 31
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SIGNED 0
+
+/* Register EUR_CR_OCP_DEBUG_STATUS */
+#define EUR_CR_OCP_DEBUG_STATUS             0xFF0C
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_MASK 0x00000003UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SHIFT 0
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_MASK 0x00000004UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_SHIFT 2
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_MASK 0x00000008UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_SHIFT 3
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_MASK 0x00000030UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_SHIFT 4
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_MASK 0x000000C0UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_SHIFT 6
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_MASK 0x00000300UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_SHIFT 8
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_MASK 0x00000400UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_SHIFT 10
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_MASK 0x00000800UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_SHIFT 11
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_MASK 0x00001000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_SHIFT 12
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_MASK 0x00006000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_SHIFT 13
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_MASK 0x00008000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_SHIFT 15
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_MASK 0x00010000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_SHIFT 16
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_MASK 0x00020000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_SHIFT 17
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_MASK 0x001C0000UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_SHIFT 18
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_MASK 0x03E00000UL
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_SHIFT 21
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_MASK 0x04000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_SHIFT 26
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_MASK 0x08000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_SHIFT 27
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_MASK 0x10000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_SHIFT 28
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_MASK 0x20000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_SHIFT 29
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_MASK 0x40000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_SHIFT 30
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_MASK 0x80000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SHIFT 31
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SIGNED 0
+
+
+#endif /* _OCPDEFS_H_ */
+
+/*****************************************************************************
+ End of file (ocpdefs.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx520defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx520defs.h
new file mode 100644
index 0000000..80c3363
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx520defs.h
@@ -0,0 +1,555 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX520.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX520DEFS_KM_H_
+#define _SGX520DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x00003000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00030000U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK     0x00300000U
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT    20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0004
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00001000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00010000U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK  0x00100000U
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x0008
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x00003000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00030000U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK  0x00300000U
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000040U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   6
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012C
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_TIMER */
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+/* Register EUR_CR_USE_CODE_BASE_0 */
+#define EUR_CR_USE_CODE_BASE_0              0x0A0C
+#define EUR_CR_USE_CODE_BASE_ADDR_00_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_00_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_00_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_1 */
+#define EUR_CR_USE_CODE_BASE_1              0x0A10
+#define EUR_CR_USE_CODE_BASE_ADDR_01_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_01_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_01_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_2 */
+#define EUR_CR_USE_CODE_BASE_2              0x0A14
+#define EUR_CR_USE_CODE_BASE_ADDR_02_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_02_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_02_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_3 */
+#define EUR_CR_USE_CODE_BASE_3              0x0A18
+#define EUR_CR_USE_CODE_BASE_ADDR_03_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_03_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_03_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_4 */
+#define EUR_CR_USE_CODE_BASE_4              0x0A1C
+#define EUR_CR_USE_CODE_BASE_ADDR_04_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_04_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_04_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_5 */
+#define EUR_CR_USE_CODE_BASE_5              0x0A20
+#define EUR_CR_USE_CODE_BASE_ADDR_05_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_05_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_05_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_6 */
+#define EUR_CR_USE_CODE_BASE_6              0x0A24
+#define EUR_CR_USE_CODE_BASE_ADDR_06_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_06_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_06_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_7 */
+#define EUR_CR_USE_CODE_BASE_7              0x0A28
+#define EUR_CR_USE_CODE_BASE_ADDR_07_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_07_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_07_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_8 */
+#define EUR_CR_USE_CODE_BASE_8              0x0A2C
+#define EUR_CR_USE_CODE_BASE_ADDR_08_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_08_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_08_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_9 */
+#define EUR_CR_USE_CODE_BASE_9              0x0A30
+#define EUR_CR_USE_CODE_BASE_ADDR_09_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_09_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_09_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_10 */
+#define EUR_CR_USE_CODE_BASE_10             0x0A34
+#define EUR_CR_USE_CODE_BASE_ADDR_10_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_10_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_10_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_11 */
+#define EUR_CR_USE_CODE_BASE_11             0x0A38
+#define EUR_CR_USE_CODE_BASE_ADDR_11_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_11_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_11_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_12 */
+#define EUR_CR_USE_CODE_BASE_12             0x0A3C
+#define EUR_CR_USE_CODE_BASE_ADDR_12_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_12_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_12_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_13 */
+#define EUR_CR_USE_CODE_BASE_13             0x0A40
+#define EUR_CR_USE_CODE_BASE_ADDR_13_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_13_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_13_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_14 */
+#define EUR_CR_USE_CODE_BASE_14             0x0A44
+#define EUR_CR_USE_CODE_BASE_ADDR_14_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_14_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_14_SHIFT    20
+/* Register EUR_CR_USE_CODE_BASE_15 */
+#define EUR_CR_USE_CODE_BASE_15             0x0A48
+#define EUR_CR_USE_CODE_BASE_ADDR_15_MASK   0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_DM_15_MASK     0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_15_SHIFT    20
+/* Register EUR_CR_PDS_EXEC_BASE */
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV2 */
+#define EUR_CR_PDS_INV2                     0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV2_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+/* Register EUR_CR_PDS_PC_BASE */
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x3FFFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x000FFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x00300000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       20
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX520DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx530defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx530defs.h
new file mode 100644
index 0000000..3223feb
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx530defs.h
@@ -0,0 +1,542 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX530.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX530DEFS_KM_H_
+#define _SGX530DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK      0x00000003U
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT     0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x00003000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00030000U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK     0x00300000U
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT    20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK   0x00000001U
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT  0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00001000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00010000U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK  0x00100000U
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK   0x00000003U
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT  0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x00003000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00030000U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK  0x00300000U
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK   0x00000002U
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT  1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000040U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   6
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_PDS_EXEC_BASE */
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV2 */
+#define EUR_CR_PDS_INV2                     0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV2_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+/* Register EUR_CR_PDS_PC_BASE */
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x3FFFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TWOD_REQ_BASE */
+#define EUR_CR_BIF_TWOD_REQ_BASE            0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK  0x0FF00000U
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+/* Register EUR_CR_2D_BLIT_STATUS */
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       24
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+#define EUR_CR_MNE_CR_CTRL						0x0D00
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_MASK		0x00010000U
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_N_SHIFT		16
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_MASK			0x00008000U
+#define EUR_CR_MNE_CR_CTRL_BYP_CC_SHIFT			15
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_MASK	0x00007800U
+#define EUR_CR_MNE_CR_CTRL_USE_INVAL_ADDR_SHIFT	11
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_MASK		0x00000400U
+#define EUR_CR_MNE_CR_CTRL_BYPASS_ALL_SHIFT		10
+#define EUR_CR_MNE_CR_CTRL_BYPASS_MASK			0x000003E0U
+#define EUR_CR_MNE_CR_CTRL_BYPASS_SHIFT			5
+#define EUR_CR_MNE_CR_CTRL_PAUSE_MASK			0x00000010U
+#define EUR_CR_MNE_CR_CTRL_PAUSE_SHIFT			4
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_MASK		0x0000000EU
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT		1
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_PDS_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+2)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_USEC_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT+1)
+#define EUR_CR_MNE_CR_CTRL_INVAL_PREQ_CACHE_MASK (1UL<<EUR_CR_MNE_CR_CTRL_INVAL_PREQ_SHIFT)
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_MASK		0x00000001U
+#define EUR_CR_MNE_CR_CTRL_INVAL_ALL_SHIFT		0
+#define EUR_CR_MNE_CR_USE_INVAL					0x0D04
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_MASK		0xFFFFFFFFU
+#define EUR_CR_MNE_CR_USE_INVAL_ADDR_SHIFT		0
+#define EUR_CR_MNE_CR_STAT					0x0D08
+#define EUR_CR_MNE_CR_STAT_PAUSED_MASK		0x00000400U
+#define EUR_CR_MNE_CR_STAT_PAUSED_SHIFT		10
+#define EUR_CR_MNE_CR_STAT_READS_MASK		0x000003FFU
+#define EUR_CR_MNE_CR_STAT_READS_SHIFT		0
+#define EUR_CR_MNE_CR_STAT_STATS			0x0D0C
+#define EUR_CR_MNE_CR_STAT_STATS_RST_MASK	0x000FFFF0U
+#define EUR_CR_MNE_CR_STAT_STATS_RST_SHIFT	4
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_MASK	0x0000000FU
+#define EUR_CR_MNE_CR_STAT_STATS_SEL_SHIFT	0
+#define EUR_CR_MNE_CR_STAT_STATS_OUT				0x0D10
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_MASK		0xFFFFFFFFU
+#define EUR_CR_MNE_CR_STAT_STATS_OUT_VALUE_SHIFT	0
+#define EUR_CR_MNE_CR_EVENT_STATUS				0x0D14
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_MASK	0x00000001U
+#define EUR_CR_MNE_CR_EVENT_STATUS_INVAL_SHIFT	0
+#define EUR_CR_MNE_CR_EVENT_CLEAR				0x0D18
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_MASK	0x00000001U
+#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT	0
+#define EUR_CR_MNE_CR_CTRL_INVAL				0x0D20
+
+#endif /* _SGX530DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx531defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx531defs.h
new file mode 100644
index 0000000..3295d89
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx531defs.h
@@ -0,0 +1,601 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX531.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX531DEFS_KM_H_
+#define _SGX531DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK     0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT    14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK  0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+/* Register EUR_CR_CLKGATECTL2 */
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK  0x00003000U
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK  0x00300000U
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK  0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000U
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000U
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  20
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK  0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  18
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK    0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK   0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT  6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK    0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT   8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK    0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT   9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK   0x00001000U
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT  12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK    0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT   13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK    0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT   14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    17
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_TIMER */
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+/* Register EUR_CR_EVENT_KICK1 */
+#define EUR_CR_EVENT_KICK1                  0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+/* Register EUR_CR_PDS_EXEC_BASE */
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+/* Register EUR_CR_EVENT_KICK2 */
+#define EUR_CR_EVENT_KICK2                  0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+/* Register EUR_CR_EVENT_KICK3 */
+#define EUR_CR_EVENT_KICK3                  0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+/* Register EUR_CR_PDS_PC_BASE */
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x00FFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+/* Register EUR_CR_2D_BLIT_STATUS */
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       24
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX531DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx535defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx535defs.h
new file mode 100644
index 0000000..8039da4
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx535defs.h
@@ -0,0 +1,739 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX535.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX535DEFS_KM_H_
+#define _SGX535DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK      0x00000003U
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT     0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x00003000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00030000U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK     0x00300000U
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT    20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK   0x00000001
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT  0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00001000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00010000U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK  0x00100000U
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK   0x00000003U
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT  0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x00003000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00030000U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK  0x00300000U
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK   0x00000002U
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT  1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000040U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   6
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000080U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  7
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000040U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  6
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000020U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  5
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_PDS_EXEC_BASE */
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0xFFF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV2 */
+#define EUR_CR_PDS_INV2                     0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV2_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+/* Register EUR_CR_PDS_PC_BASE */
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x3FFFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00010000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 16
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+/* Register EUR_CR_BIF_TILE0 */
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE1 */
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE2 */
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE3 */
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE4 */
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE5 */
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE6 */
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE7 */
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE8 */
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+/* Register EUR_CR_BIF_TILE9 */
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+/* Register EUR_CR_BIF_DIR_LIST_BASE1 */
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE2 */
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE3 */
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE4 */
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE5 */
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE6 */
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE7 */
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE8 */
+#define EUR_CR_BIF_DIR_LIST_BASE8           0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE9 */
+#define EUR_CR_BIF_DIR_LIST_BASE9           0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE10 */
+#define EUR_CR_BIF_DIR_LIST_BASE10          0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE11 */
+#define EUR_CR_BIF_DIR_LIST_BASE11          0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE12 */
+#define EUR_CR_BIF_DIR_LIST_BASE12          0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE13 */
+#define EUR_CR_BIF_DIR_LIST_BASE13          0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE14 */
+#define EUR_CR_BIF_DIR_LIST_BASE14          0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE15 */
+#define EUR_CR_BIF_DIR_LIST_BASE15          0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_BANK_SET */
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_MASK     0x000003FFU
+#define EUR_CR_BIF_BANK_SET_SELECT_SHIFT    0
+/* Register EUR_CR_BIF_BANK0 */
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK    0x00000F00U
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK      0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT     16
+/* Register EUR_CR_BIF_BANK1 */
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK    0x00000F00U
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK      0x000F0000U
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT     16
+/* Register EUR_CR_BIF_ADT_TTE */
+#define EUR_CR_BIF_ADT_TTE                  0x0C80
+#define EUR_CR_BIF_ADT_TTE_VALUE_MASK       0x000000FFU
+#define EUR_CR_BIF_ADT_TTE_VALUE_SHIFT      0
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TWOD_REQ_BASE */
+#define EUR_CR_BIF_TWOD_REQ_BASE            0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK  0xFFF00000U
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_MEM_ARB_FLOWRATES_1 */
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1      0x0C94
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_MASK 0x00007000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_SHIFT 12
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_MASK 0x00038000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_SHIFT 15
+/* Register EUR_CR_BIF_MEM_ARB_FLOWRATES_2 */
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2      0x0C98
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_SHIFT 9
+/* Register EUR_CR_BIF_MEM_ARB_CONFIG */
+#define EUR_CR_BIF_MEM_ARB_CONFIG           0x0CA0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_MASK 0x0000000FU
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_MASK 0x00000FF0U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT 4
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_MASK 0x00FFF000U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT 12
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+/* Register EUR_CR_BIF_BANK_STATUS */
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+/* Register EUR_CR_2D_BLIT_STATUS */
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Register EUR_CR_2D_SOCIF */
+#define EUR_CR_2D_SOCIF                     0x0E18
+#define EUR_CR_2D_SOCIF_FREESPACE_MASK      0x000000FFU
+#define EUR_CR_2D_SOCIF_FREESPACE_SHIFT     0
+/* Register EUR_CR_2D_ALPHA */
+#define EUR_CR_2D_ALPHA                     0x0E1C
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_MASK  0x0000FF00U
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_SHIFT 8
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_MASK 0x000000FFU
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_SHIFT 0
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       25
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX535DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx540defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx540defs.h
new file mode 100644
index 0000000..47080c7
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx540defs.h
@@ -0,0 +1,605 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX540.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX540DEFS_KM_H_
+#define _SGX540DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK     0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT    14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK  0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+/* Register EUR_CR_CLKGATECTL2 */
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK  0x00003000U
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK  0x00300000U
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK  0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000U
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000U
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  20
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK  0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  18
+/* Register EUR_CR_POWER */
+#define EUR_CR_POWER                        0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK      0x00000001U
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT     0
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK    0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK   0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT  6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK    0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT   8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK    0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT   9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK   0x00001000U
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT  12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK    0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT   13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK    0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT   14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    17
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK   0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT  17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_TIMER */
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+/* Register EUR_CR_EVENT_KICK1 */
+#define EUR_CR_EVENT_KICK1                  0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+/* Register EUR_CR_PDS_EXEC_BASE */
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+/* Register EUR_CR_EVENT_KICK2 */
+#define EUR_CR_EVENT_KICK2                  0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+/* Register EUR_CR_EVENT_KICK3 */
+#define EUR_CR_EVENT_KICK3                  0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+/* Register EUR_CR_PDS_PC_BASE */
+#define EUR_CR_PDS_PC_BASE                  0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK     0x00FFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT    0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK      0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT     0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK    0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT   14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+/* Register EUR_CR_2D_BLIT_STATUS */
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       24
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX540DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx543_v1.164defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx543_v1.164defs.h
new file mode 100644
index 0000000..8c8b353
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx543_v1.164defs.h
@@ -0,0 +1,1396 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX543_V1.164.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX543_V1_164DEFS_KM_H_
+#define _SGX543_V1_164DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_TE_CLKG_SIGNED    0
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK     0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT    14
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     18
+#define EUR_CR_CLKGATECTL_TA_CLKG_SIGNED    0
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SIGNED 0
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK  0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATECTL2 */
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_MASK 0x00C00000U
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_SHIFT 22
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_MASK 0x03000000U
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_SHIFT 24
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_MASK 0x0C000000U
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SHIFT 26
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK  0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  20
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_MASK 0x00200000U
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_SHIFT 21
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_MASK 0x00400000U
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_SHIFT 22
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_MASK 0x00800000U
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_SHIFT 23
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_MASK 0x01000000U
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SHIFT 24
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SIGNED 0
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK  0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  18
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_MASK 0x00300000U
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SIGNED 0
+/* Register EUR_CR_POWER */
+#define EUR_CR_POWER                        0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK      0x00000001U
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT     0
+#define EUR_CR_POWER_PIPE_DISABLE_SIGNED    0
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0020
+#define EUR_CR_CORE_ID_CONFIG_MULTI_MASK    0x00000001U
+#define EUR_CR_CORE_ID_CONFIG_MULTI_SHIFT   0
+#define EUR_CR_CORE_ID_CONFIG_MULTI_SIGNED  0
+#define EUR_CR_CORE_ID_CONFIG_BASE_MASK     0x00000002U
+#define EUR_CR_CORE_ID_CONFIG_BASE_SHIFT    1
+#define EUR_CR_CORE_ID_CONFIG_BASE_SIGNED   0
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x000000FCU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         2
+#define EUR_CR_CORE_ID_CONFIG_SIGNED        0
+#define EUR_CR_CORE_ID_CONFIG_CORES_MASK    0x00000F00U
+#define EUR_CR_CORE_ID_CONFIG_CORES_SHIFT   8
+#define EUR_CR_CORE_ID_CONFIG_CORES_SIGNED  0
+#define EUR_CR_CORE_ID_CONFIG_SLC_MASK      0x0000F000U
+#define EUR_CR_CORE_ID_CONFIG_SLC_SHIFT     12
+#define EUR_CR_CORE_ID_CONFIG_SLC_SIGNED    0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_ID_ID_SIGNED            0
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SIGNED 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MINOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_MAJOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SIGNED 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_BIF_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK    0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_VDM_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_DPM_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_TE_RESET_SIGNED   0
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_MTE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_ISP_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK   0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT  6
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   7
+#define EUR_CR_SOFT_RESET_TSP_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK    0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT   8
+#define EUR_CR_SOFT_RESET_PDS_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK    0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT   9
+#define EUR_CR_SOFT_RESET_PBE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK    0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT   13
+#define EUR_CR_SOFT_RESET_ITR_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK    0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT   14
+#define EUR_CR_SOFT_RESET_TEX_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   15
+#define EUR_CR_SOFT_RESET_USE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    17
+#define EUR_CR_SOFT_RESET_TA_RESET_SIGNED   0
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK 0x00040000U
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_SHIFT 18
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK 0x00080000U
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SHIFT 19
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012C
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TIMER_SIGNED    0
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_TIMER */
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+#define EUR_CR_TIMER_VALUE_SIGNED           0
+/* Register EUR_CR_EVENT_KICK1 */
+#define EUR_CR_EVENT_KICK1                  0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK1_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICK2 */
+#define EUR_CR_EVENT_KICK2                  0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK2_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICKER_ADDRESS_SIGNED  0
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_KICK_NOW_SIGNED        0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_ENABLE_SIGNED    0
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_EVENT_TIMER_VALUE_SIGNED     0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV0_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1_DSC_SIGNED          0
+/* Register EUR_CR_EVENT_KICK3 */
+#define EUR_CR_EVENT_KICK3                  0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK3_NOW_SIGNED       0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_INV_CSC_KICK_SIGNED      0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_NOREORDER_SIGNED    0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_PAUSE_SIGNED        0
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SIGNED  0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_MASK 0x00010000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_SHIFT 16
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_MASK 0x00020000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SHIFT 17
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_MASK 0x00040000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SHIFT 18
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK  0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK 0x00070000U
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SHIFT 16
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SIGNED 0
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_CID_MASK           0x0000000FU
+#define EUR_CR_BIF_FAULT_CID_SHIFT          0
+#define EUR_CR_BIF_FAULT_CID_SIGNED         0
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_SB_SIGNED          0
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_FAULT_ADDR_SIGNED        0
+/* Register EUR_CR_BIF_TILE0 */
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE0_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE1 */
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE2 */
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE3 */
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE4 */
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE5 */
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE6 */
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE7 */
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE8 */
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE9 */
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9_CFG_SIGNED         0
+/* Register EUR_CR_BIF_CTRL_INVAL */
+#define EUR_CR_BIF_CTRL_INVAL               0x0C34
+#define EUR_CR_BIF_CTRL_INVAL_PTE_MASK      0x00000004U
+#define EUR_CR_BIF_CTRL_INVAL_PTE_SHIFT     2
+#define EUR_CR_BIF_CTRL_INVAL_PTE_SIGNED    0
+#define EUR_CR_BIF_CTRL_INVAL_ALL_MASK      0x00000008U
+#define EUR_CR_BIF_CTRL_INVAL_ALL_SHIFT     3
+#define EUR_CR_BIF_CTRL_INVAL_ALL_SIGNED    0
+/* Register EUR_CR_BIF_DIR_LIST_BASE1 */
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE2 */
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE3 */
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE4 */
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE5 */
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE6 */
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE7 */
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_SET */
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK  0x00000001U
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_MASK  0x0000000CU
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SHIFT 2
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_MASK 0x00000010U
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SHIFT 4
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_MASK  0x000000C0U
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SHIFT 6
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_MASK 0x00000100U
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SHIFT 8
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200U
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SIGNED 0
+/* Register EUR_CR_BIF_BANK0 */
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_3D_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_MASK    0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT   16
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_SIGNED  0
+/* Register EUR_CR_BIF_BANK1 */
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_3D_SIGNED    0
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SIGNED 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_STATUS */
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SIGNED 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SIGNED 0
+/* Register EUR_CR_BIF_MMU_CTRL */
+#define EUR_CR_BIF_MMU_CTRL                 0x0CD0
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_MASK 0x00000006U
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT 1
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_MASK 0x00000008U
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_SHIFT 3
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK 0x00000010U
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_SHIFT 4
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_SIGNED 0
+/* Register EUR_CR_2D_BLIT_STATUS */
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SIGNED 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SIGNED   0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SIGNED 0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_START */
+#define EUR_CR_BREAKPOINT0_START            0x0F44
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_END */
+#define EUR_CR_BREAKPOINT0_END              0x0F48
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0 */
+#define EUR_CR_BREAKPOINT0                  0x0F4C
+#define EUR_CR_BREAKPOINT0_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT0_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT0_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_START */
+#define EUR_CR_BREAKPOINT1_START            0x0F50
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_END */
+#define EUR_CR_BREAKPOINT1_END              0x0F54
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1 */
+#define EUR_CR_BREAKPOINT1                  0x0F58
+#define EUR_CR_BREAKPOINT1_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT1_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT1_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_START */
+#define EUR_CR_BREAKPOINT2_START            0x0F5C
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_END */
+#define EUR_CR_BREAKPOINT2_END              0x0F60
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2 */
+#define EUR_CR_BREAKPOINT2                  0x0F64
+#define EUR_CR_BREAKPOINT2_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT2_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT2_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_START */
+#define EUR_CR_BREAKPOINT3_START            0x0F68
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_END */
+#define EUR_CR_BREAKPOINT3_END              0x0F6C
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3 */
+#define EUR_CR_BREAKPOINT3                  0x0F70
+#define EUR_CR_BREAKPOINT3_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT3_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT3_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT_READ */
+#define EUR_CR_BREAKPOINT_READ              0x0F74
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT_TRAP */
+#define EUR_CR_BREAKPOINT_TRAP              0x0F78
+#define EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_BREAKPOINT */
+#define EUR_CR_BREAKPOINT                   0x0F7C
+#define EUR_CR_BREAKPOINT_MODULE_ID_MASK    0x000003C0U
+#define EUR_CR_BREAKPOINT_MODULE_ID_SHIFT   6
+#define EUR_CR_BREAKPOINT_MODULE_ID_SIGNED  0
+#define EUR_CR_BREAKPOINT_ID_MASK           0x00000030U
+#define EUR_CR_BREAKPOINT_ID_SHIFT          4
+#define EUR_CR_BREAKPOINT_ID_SIGNED         0
+#define EUR_CR_BREAKPOINT_UNTRAPPED_MASK    0x00000008U
+#define EUR_CR_BREAKPOINT_UNTRAPPED_SHIFT   3
+#define EUR_CR_BREAKPOINT_UNTRAPPED_SIGNED  0
+#define EUR_CR_BREAKPOINT_TRAPPED_MASK      0x00000004U
+#define EUR_CR_BREAKPOINT_TRAPPED_SHIFT     2
+#define EUR_CR_BREAKPOINT_TRAPPED_SIGNED    0
+/* Register EUR_CR_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_BREAKPOINT_TRAP_INFO0        0x0F80
+#define EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_BREAKPOINT_TRAP_INFO1        0x0F84
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_0 */
+#define EUR_CR_USE_CODE_BASE_0              0x0A0C
+#define EUR_CR_USE_CODE_BASE_ADDR_00_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_00_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_00_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_00_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_1 */
+#define EUR_CR_USE_CODE_BASE_1              0x0A10
+#define EUR_CR_USE_CODE_BASE_ADDR_01_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_01_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_01_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_01_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_2 */
+#define EUR_CR_USE_CODE_BASE_2              0x0A14
+#define EUR_CR_USE_CODE_BASE_ADDR_02_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_02_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_02_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_02_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_3 */
+#define EUR_CR_USE_CODE_BASE_3              0x0A18
+#define EUR_CR_USE_CODE_BASE_ADDR_03_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_03_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_03_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_03_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_4 */
+#define EUR_CR_USE_CODE_BASE_4              0x0A1C
+#define EUR_CR_USE_CODE_BASE_ADDR_04_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_04_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_04_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_04_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_5 */
+#define EUR_CR_USE_CODE_BASE_5              0x0A20
+#define EUR_CR_USE_CODE_BASE_ADDR_05_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_05_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_05_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_05_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_6 */
+#define EUR_CR_USE_CODE_BASE_6              0x0A24
+#define EUR_CR_USE_CODE_BASE_ADDR_06_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_06_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_06_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_06_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_7 */
+#define EUR_CR_USE_CODE_BASE_7              0x0A28
+#define EUR_CR_USE_CODE_BASE_ADDR_07_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_07_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_07_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_07_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_8 */
+#define EUR_CR_USE_CODE_BASE_8              0x0A2C
+#define EUR_CR_USE_CODE_BASE_ADDR_08_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_08_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_08_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_08_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_9 */
+#define EUR_CR_USE_CODE_BASE_9              0x0A30
+#define EUR_CR_USE_CODE_BASE_ADDR_09_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_09_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_09_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_09_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_10 */
+#define EUR_CR_USE_CODE_BASE_10             0x0A34
+#define EUR_CR_USE_CODE_BASE_ADDR_10_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_10_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_10_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_10_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_11 */
+#define EUR_CR_USE_CODE_BASE_11             0x0A38
+#define EUR_CR_USE_CODE_BASE_ADDR_11_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_11_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_11_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_11_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_12 */
+#define EUR_CR_USE_CODE_BASE_12             0x0A3C
+#define EUR_CR_USE_CODE_BASE_ADDR_12_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_12_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_12_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_12_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_13 */
+#define EUR_CR_USE_CODE_BASE_13             0x0A40
+#define EUR_CR_USE_CODE_BASE_ADDR_13_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_13_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_13_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_13_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_14 */
+#define EUR_CR_USE_CODE_BASE_14             0x0A44
+#define EUR_CR_USE_CODE_BASE_ADDR_14_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_14_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_14_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_14_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_15 */
+#define EUR_CR_USE_CODE_BASE_15             0x0A48
+#define EUR_CR_USE_CODE_BASE_ADDR_15_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_15_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_15_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_15_SIGNED   0
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_ADDR_SIGNED    0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       26
+#define EUR_CR_USE_CODE_BASE_DM_SIGNED      0
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX543_V1_164DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx543defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx543defs.h
new file mode 100644
index 0000000..0d3568d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx543defs.h
@@ -0,0 +1,1487 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX543.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX543DEFS_KM_H_
+#define _SGX543DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_TE_CLKG_SIGNED    0
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK     0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT    14
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     18
+#define EUR_CR_CLKGATECTL_TA_CLKG_SIGNED    0
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SIGNED 0
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK  0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATECTL2 */
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_MASK 0x00C00000U
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_SHIFT 22
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_MASK 0x03000000U
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_SHIFT 24
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_MASK 0x0C000000U
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SHIFT 26
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK  0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  20
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_MASK 0x00200000U
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_SHIFT 21
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_MASK 0x00400000U
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_SHIFT 22
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_MASK 0x00800000U
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_SHIFT 23
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_MASK 0x01000000U
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SHIFT 24
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SIGNED 0
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK  0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  18
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_MASK 0x00300000U
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SIGNED 0
+/* Register EUR_CR_POWER */
+#define EUR_CR_POWER                        0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK      0x00000001U
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT     0
+#define EUR_CR_POWER_PIPE_DISABLE_SIGNED    0
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0020
+#define EUR_CR_CORE_ID_CONFIG_MULTI_MASK    0x00000001U
+#define EUR_CR_CORE_ID_CONFIG_MULTI_SHIFT   0
+#define EUR_CR_CORE_ID_CONFIG_MULTI_SIGNED  0
+#define EUR_CR_CORE_ID_CONFIG_BASE_MASK     0x00000002U
+#define EUR_CR_CORE_ID_CONFIG_BASE_SHIFT    1
+#define EUR_CR_CORE_ID_CONFIG_BASE_SIGNED   0
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x000000FCU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         2
+#define EUR_CR_CORE_ID_CONFIG_SIGNED        0
+#define EUR_CR_CORE_ID_CONFIG_CORES_MASK    0x00000F00U
+#define EUR_CR_CORE_ID_CONFIG_CORES_SHIFT   8
+#define EUR_CR_CORE_ID_CONFIG_CORES_SIGNED  0
+#define EUR_CR_CORE_ID_CONFIG_SLC_MASK      0x0000F000U
+#define EUR_CR_CORE_ID_CONFIG_SLC_SHIFT     12
+#define EUR_CR_CORE_ID_CONFIG_SLC_SIGNED    0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_ID_ID_SIGNED            0
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SIGNED 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MINOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_MAJOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SIGNED 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_BIF_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK    0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_VDM_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_DPM_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_TE_RESET_SIGNED   0
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_MTE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_ISP_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK   0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT  6
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   7
+#define EUR_CR_SOFT_RESET_TSP_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK    0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT   8
+#define EUR_CR_SOFT_RESET_PDS_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK    0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT   9
+#define EUR_CR_SOFT_RESET_PBE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK    0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT   13
+#define EUR_CR_SOFT_RESET_ITR_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK    0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT   14
+#define EUR_CR_SOFT_RESET_TEX_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   15
+#define EUR_CR_SOFT_RESET_USE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    17
+#define EUR_CR_SOFT_RESET_TA_RESET_SIGNED   0
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK 0x00040000U
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_SHIFT 18
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK 0x00080000U
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SHIFT 19
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012C
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TIMER_SIGNED    0
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_TIMER */
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+#define EUR_CR_TIMER_VALUE_SIGNED           0
+/* Register EUR_CR_EVENT_KICK1 */
+#define EUR_CR_EVENT_KICK1                  0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK1_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICK2 */
+#define EUR_CR_EVENT_KICK2                  0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK2_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICKER_ADDRESS_SIGNED  0
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_KICK_NOW_SIGNED        0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_ENABLE_SIGNED    0
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_EVENT_TIMER_VALUE_SIGNED     0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV0_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1_DSC_SIGNED          0
+/* Register EUR_CR_EVENT_KICK3 */
+#define EUR_CR_EVENT_KICK3                  0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK3_NOW_SIGNED       0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_INV_CSC_KICK_SIGNED      0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_NOREORDER_SIGNED    0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_PAUSE_SIGNED        0
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SIGNED  0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_MASK 0x00010000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_SHIFT 16
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_MASK 0x00020000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SHIFT 17
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_MASK 0x00040000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SHIFT 18
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK  0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK 0x00070000U
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SHIFT 16
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SIGNED 0
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_CID_MASK           0x0000000FU
+#define EUR_CR_BIF_FAULT_CID_SHIFT          0
+#define EUR_CR_BIF_FAULT_CID_SIGNED         0
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_SB_SIGNED          0
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_FAULT_ADDR_SIGNED        0
+/* Register EUR_CR_BIF_TILE0 */
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE0_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE1 */
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE2 */
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE3 */
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE4 */
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE5 */
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE6 */
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE7 */
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE8 */
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE9 */
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9_CFG_SIGNED         0
+/* Register EUR_CR_BIF_CTRL_INVAL */
+#define EUR_CR_BIF_CTRL_INVAL               0x0C34
+#define EUR_CR_BIF_CTRL_INVAL_PTE_MASK      0x00000004U
+#define EUR_CR_BIF_CTRL_INVAL_PTE_SHIFT     2
+#define EUR_CR_BIF_CTRL_INVAL_PTE_SIGNED    0
+#define EUR_CR_BIF_CTRL_INVAL_ALL_MASK      0x00000008U
+#define EUR_CR_BIF_CTRL_INVAL_ALL_SHIFT     3
+#define EUR_CR_BIF_CTRL_INVAL_ALL_SIGNED    0
+/* Register EUR_CR_BIF_DIR_LIST_BASE1 */
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE2 */
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE3 */
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE4 */
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE5 */
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE6 */
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE7 */
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_SET */
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK  0x00000001U
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_MASK  0x0000000CU
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SHIFT 2
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_MASK 0x00000010U
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SHIFT 4
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_MASK  0x000000C0U
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SHIFT 6
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_MASK 0x00000100U
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SHIFT 8
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200U
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SIGNED 0
+/* Register EUR_CR_BIF_BANK0 */
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_3D_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_MASK    0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT   16
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_SIGNED  0
+/* Register EUR_CR_BIF_BANK1 */
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_3D_SIGNED    0
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SIGNED 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_STATUS */
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SIGNED 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SIGNED 0
+/* Register EUR_CR_BIF_MMU_CTRL */
+#define EUR_CR_BIF_MMU_CTRL                 0x0CD0
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_MASK 0x00000006U
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT 1
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_MASK 0x00000008U
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_SHIFT 3
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK 0x00000010U
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_SHIFT 4
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_MASK 0x00000020U
+#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SHIFT 5
+#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SIGNED 0
+/* Register EUR_CR_2D_BLIT_STATUS */
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SIGNED 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SIGNED   0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SIGNED 0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_START */
+#define EUR_CR_BREAKPOINT0_START            0x0F44
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_END */
+#define EUR_CR_BREAKPOINT0_END              0x0F48
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0 */
+#define EUR_CR_BREAKPOINT0                  0x0F4C
+#define EUR_CR_BREAKPOINT0_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT0_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT0_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_START */
+#define EUR_CR_BREAKPOINT1_START            0x0F50
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_END */
+#define EUR_CR_BREAKPOINT1_END              0x0F54
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1 */
+#define EUR_CR_BREAKPOINT1                  0x0F58
+#define EUR_CR_BREAKPOINT1_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT1_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT1_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_START */
+#define EUR_CR_BREAKPOINT2_START            0x0F5C
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_END */
+#define EUR_CR_BREAKPOINT2_END              0x0F60
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2 */
+#define EUR_CR_BREAKPOINT2                  0x0F64
+#define EUR_CR_BREAKPOINT2_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT2_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT2_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_START */
+#define EUR_CR_BREAKPOINT3_START            0x0F68
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_END */
+#define EUR_CR_BREAKPOINT3_END              0x0F6C
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3 */
+#define EUR_CR_BREAKPOINT3                  0x0F70
+#define EUR_CR_BREAKPOINT3_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT3_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT3_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT_READ */
+#define EUR_CR_BREAKPOINT_READ              0x0F74
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP */
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP    0x0F78
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT */
+#define EUR_CR_PARTITION_BREAKPOINT         0x0F7C
+#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
+#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_SHIFT 6
+#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_ID_MASK 0x00000030U
+#define EUR_CR_PARTITION_BREAKPOINT_ID_SHIFT 4
+#define EUR_CR_PARTITION_BREAKPOINT_ID_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_UNTRAPPED_MASK 0x00000008U
+#define EUR_CR_PARTITION_BREAKPOINT_UNTRAPPED_SHIFT 3
+#define EUR_CR_PARTITION_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_MASK 0x00000004U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SHIFT 2
+#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 0x0F80
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 0x0F84
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_0 */
+#define EUR_CR_USE_CODE_BASE_0              0x0A0C
+#define EUR_CR_USE_CODE_BASE_ADDR_00_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_00_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_00_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_00_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_1 */
+#define EUR_CR_USE_CODE_BASE_1              0x0A10
+#define EUR_CR_USE_CODE_BASE_ADDR_01_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_01_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_01_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_01_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_2 */
+#define EUR_CR_USE_CODE_BASE_2              0x0A14
+#define EUR_CR_USE_CODE_BASE_ADDR_02_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_02_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_02_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_02_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_3 */
+#define EUR_CR_USE_CODE_BASE_3              0x0A18
+#define EUR_CR_USE_CODE_BASE_ADDR_03_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_03_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_03_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_03_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_4 */
+#define EUR_CR_USE_CODE_BASE_4              0x0A1C
+#define EUR_CR_USE_CODE_BASE_ADDR_04_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_04_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_04_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_04_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_5 */
+#define EUR_CR_USE_CODE_BASE_5              0x0A20
+#define EUR_CR_USE_CODE_BASE_ADDR_05_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_05_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_05_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_05_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_6 */
+#define EUR_CR_USE_CODE_BASE_6              0x0A24
+#define EUR_CR_USE_CODE_BASE_ADDR_06_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_06_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_06_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_06_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_7 */
+#define EUR_CR_USE_CODE_BASE_7              0x0A28
+#define EUR_CR_USE_CODE_BASE_ADDR_07_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_07_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_07_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_07_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_8 */
+#define EUR_CR_USE_CODE_BASE_8              0x0A2C
+#define EUR_CR_USE_CODE_BASE_ADDR_08_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_08_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_08_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_08_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_9 */
+#define EUR_CR_USE_CODE_BASE_9              0x0A30
+#define EUR_CR_USE_CODE_BASE_ADDR_09_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_09_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_09_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_09_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_10 */
+#define EUR_CR_USE_CODE_BASE_10             0x0A34
+#define EUR_CR_USE_CODE_BASE_ADDR_10_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_10_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_10_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_10_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_11 */
+#define EUR_CR_USE_CODE_BASE_11             0x0A38
+#define EUR_CR_USE_CODE_BASE_ADDR_11_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_11_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_11_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_11_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_12 */
+#define EUR_CR_USE_CODE_BASE_12             0x0A3C
+#define EUR_CR_USE_CODE_BASE_ADDR_12_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_12_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_12_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_12_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_13 */
+#define EUR_CR_USE_CODE_BASE_13             0x0A40
+#define EUR_CR_USE_CODE_BASE_ADDR_13_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_13_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_13_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_13_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_14 */
+#define EUR_CR_USE_CODE_BASE_14             0x0A44
+#define EUR_CR_USE_CODE_BASE_ADDR_14_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_14_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_14_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_14_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_15 */
+#define EUR_CR_USE_CODE_BASE_15             0x0A48
+#define EUR_CR_USE_CODE_BASE_ADDR_15_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_15_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_15_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_15_SIGNED   0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP */
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP        0x0F88
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT */
+#define EUR_CR_PIPE0_BREAKPOINT             0x0F8C
+#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
+#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_SHIFT 6
+#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_ID_MASK     0x00000030U
+#define EUR_CR_PIPE0_BREAKPOINT_ID_SHIFT    4
+#define EUR_CR_PIPE0_BREAKPOINT_ID_SIGNED   0
+#define EUR_CR_PIPE0_BREAKPOINT_UNTRAPPED_MASK 0x00000008U
+#define EUR_CR_PIPE0_BREAKPOINT_UNTRAPPED_SHIFT 3
+#define EUR_CR_PIPE0_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_MASK 0x00000004U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SHIFT 2
+#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0  0x0F90
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1  0x0F94
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP */
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP        0x0F98
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT */
+#define EUR_CR_PIPE1_BREAKPOINT             0x0F9C
+#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
+#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_SHIFT 6
+#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_ID_MASK     0x00000030U
+#define EUR_CR_PIPE1_BREAKPOINT_ID_SHIFT    4
+#define EUR_CR_PIPE1_BREAKPOINT_ID_SIGNED   0
+#define EUR_CR_PIPE1_BREAKPOINT_UNTRAPPED_MASK 0x00000008U
+#define EUR_CR_PIPE1_BREAKPOINT_UNTRAPPED_SHIFT 3
+#define EUR_CR_PIPE1_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_MASK 0x00000004U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SHIFT 2
+#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0  0x0FA0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1  0x0FA4
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_ADDR_SIGNED    0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       26
+#define EUR_CR_USE_CODE_BASE_DM_SIGNED      0
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX543DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx544defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx544defs.h
new file mode 100644
index 0000000..79efcbc
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx544defs.h
@@ -0,0 +1,1487 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX544.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX544DEFS_KM_H_
+#define _SGX544DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_TE_CLKG_SIGNED    0
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK     0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT    14
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK      0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT     18
+#define EUR_CR_CLKGATECTL_TA_CLKG_SIGNED    0
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_BIF_CORE_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SIGNED 0
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK  0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATECTL2 */
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_TCU_L2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_MASK 0x00C00000U
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_SHIFT 22
+#define EUR_CR_CLKGATECTL2_DCU_L2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_MASK 0x03000000U
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_SHIFT 24
+#define EUR_CR_CLKGATECTL2_DCU1_L0L1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_MASK 0x0C000000U
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SHIFT 26
+#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK  0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_TCU_L2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK   0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT  20
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_MASK 0x00200000U
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_SHIFT 21
+#define EUR_CR_CLKGATESTATUS_DCU_L2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_MASK 0x00400000U
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_SHIFT 22
+#define EUR_CR_CLKGATESTATUS_DCU0_L0L1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_MASK 0x00800000U
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_SHIFT 23
+#define EUR_CR_CLKGATESTATUS_DCU1_L0L1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_MASK 0x01000000U
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SHIFT 24
+#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SIGNED 0
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK  0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT  18
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_MASK 0x00300000U
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SIGNED 0
+/* Register EUR_CR_POWER */
+#define EUR_CR_POWER                        0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK      0x00000001U
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT     0
+#define EUR_CR_POWER_PIPE_DISABLE_SIGNED    0
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x0020
+#define EUR_CR_CORE_ID_CONFIG_MULTI_MASK    0x00000001U
+#define EUR_CR_CORE_ID_CONFIG_MULTI_SHIFT   0
+#define EUR_CR_CORE_ID_CONFIG_MULTI_SIGNED  0
+#define EUR_CR_CORE_ID_CONFIG_BASE_MASK     0x00000002U
+#define EUR_CR_CORE_ID_CONFIG_BASE_SHIFT    1
+#define EUR_CR_CORE_ID_CONFIG_BASE_SIGNED   0
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x000000FCU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         2
+#define EUR_CR_CORE_ID_CONFIG_SIGNED        0
+#define EUR_CR_CORE_ID_CONFIG_CORES_MASK    0x00000F00U
+#define EUR_CR_CORE_ID_CONFIG_CORES_SHIFT   8
+#define EUR_CR_CORE_ID_CONFIG_CORES_SIGNED  0
+#define EUR_CR_CORE_ID_CONFIG_SLC_MASK      0x0000F000U
+#define EUR_CR_CORE_ID_CONFIG_SLC_SHIFT     12
+#define EUR_CR_CORE_ID_CONFIG_SLC_SIGNED    0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_ID_ID_SIGNED            0
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SIGNED 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MINOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_MAJOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SIGNED 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_BIF_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK    0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_VDM_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   2
+#define EUR_CR_SOFT_RESET_DPM_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK     0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT    3
+#define EUR_CR_SOFT_RESET_TE_RESET_SIGNED   0
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_MTE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_ISP_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK   0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT  6
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   7
+#define EUR_CR_SOFT_RESET_TSP_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK    0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT   8
+#define EUR_CR_SOFT_RESET_PDS_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK    0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT   9
+#define EUR_CR_SOFT_RESET_PBE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_TCU_L2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK    0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT   13
+#define EUR_CR_SOFT_RESET_ITR_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK    0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT   14
+#define EUR_CR_SOFT_RESET_TEX_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   15
+#define EUR_CR_SOFT_RESET_USE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    17
+#define EUR_CR_SOFT_RESET_TA_RESET_SIGNED   0
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK 0x00040000U
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_SHIFT 18
+#define EUR_CR_SOFT_RESET_DCU_L2_RESET_SIGNED 0
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK 0x00080000U
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SHIFT 19
+#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_SHIFT 10
+#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_SHIFT 9
+#define EUR_CR_EVENT_STATUS2_MTE_CONTEXT_DRAINED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_SHIFT 8
+#define EUR_CR_EVENT_STATUS2_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SHIFT 7
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SHIFT 6
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_SHIFT 5
+#define EUR_CR_EVENT_STATUS2_TE_RGNHDR_INIT_COMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  4
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  3
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  2
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012C
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TIMER_SIGNED    0
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_TCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_TIMER */
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+#define EUR_CR_TIMER_VALUE_SIGNED           0
+/* Register EUR_CR_EVENT_KICK1 */
+#define EUR_CR_EVENT_KICK1                  0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK1_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICK2 */
+#define EUR_CR_EVENT_KICK2                  0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK2_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICKER_ADDRESS_SIGNED  0
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_KICK_NOW_SIGNED        0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_ENABLE_SIGNED    0
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_EVENT_TIMER_VALUE_SIGNED     0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV0_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1_DSC_SIGNED          0
+/* Register EUR_CR_EVENT_KICK3 */
+#define EUR_CR_EVENT_KICK3                  0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK3_NOW_SIGNED       0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_INV_CSC_KICK_SIGNED      0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_NOREORDER_SIGNED    0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_PAUSE_SIGNED        0
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SIGNED  0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TA_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_MASK 0x00010000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_SHIFT 16
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PTLA_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_MASK 0x00020000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SHIFT 17
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_MASK 0x00040000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SHIFT 18
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK  0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK 0x00070000U
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SHIFT 16
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SIGNED 0
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_CID_MASK           0x0000000FU
+#define EUR_CR_BIF_FAULT_CID_SHIFT          0
+#define EUR_CR_BIF_FAULT_CID_SIGNED         0
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_SB_SIGNED          0
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_FAULT_ADDR_SIGNED        0
+/* Register EUR_CR_BIF_TILE0 */
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE0_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE1 */
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE2 */
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE3 */
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE4 */
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE5 */
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE6 */
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE7 */
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE8 */
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE9 */
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9_CFG_SIGNED         0
+/* Register EUR_CR_BIF_CTRL_INVAL */
+#define EUR_CR_BIF_CTRL_INVAL               0x0C34
+#define EUR_CR_BIF_CTRL_INVAL_PTE_MASK      0x00000004U
+#define EUR_CR_BIF_CTRL_INVAL_PTE_SHIFT     2
+#define EUR_CR_BIF_CTRL_INVAL_PTE_SIGNED    0
+#define EUR_CR_BIF_CTRL_INVAL_ALL_MASK      0x00000008U
+#define EUR_CR_BIF_CTRL_INVAL_ALL_SHIFT     3
+#define EUR_CR_BIF_CTRL_INVAL_ALL_SIGNED    0
+/* Register EUR_CR_BIF_DIR_LIST_BASE1 */
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE2 */
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE3 */
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE4 */
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE5 */
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE6 */
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE7 */
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_SET */
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK  0x00000001U
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_MASK  0x0000000CU
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SHIFT 2
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_MASK 0x00000010U
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SHIFT 4
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_MASK  0x000000C0U
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SHIFT 6
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_MASK 0x00000100U
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SHIFT 8
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200U
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SIGNED 0
+/* Register EUR_CR_BIF_BANK0 */
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_3D_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_MASK    0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT   16
+#define EUR_CR_BIF_BANK0_INDEX_PTLA_SIGNED  0
+/* Register EUR_CR_BIF_BANK1 */
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_3D_SIGNED    0
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SIGNED 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_STATUS */
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SIGNED 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SIGNED 0
+/* Register EUR_CR_BIF_MMU_CTRL */
+#define EUR_CR_BIF_MMU_CTRL                 0x0CD0
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
+#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_MASK 0x00000006U
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT 1
+#define EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_MASK 0x00000008U
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_SHIFT 3
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_WRITE_BURST_COLLATE_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK 0x00000010U
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_SHIFT 4
+#define EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_SIGNED 0
+#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_MASK 0x00000020U
+#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SHIFT 5
+#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SIGNED 0
+/* Register EUR_CR_2D_BLIT_STATUS */
+#define EUR_CR_2D_BLIT_STATUS               0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SIGNED 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK     0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT    24
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SIGNED   0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
+#define EUR_CR_2D_VIRTUAL_FIFO_0            0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SIGNED 0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
+#define EUR_CR_2D_VIRTUAL_FIFO_1            0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SIGNED 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_START */
+#define EUR_CR_BREAKPOINT0_START            0x0F44
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT0_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_END */
+#define EUR_CR_BREAKPOINT0_END              0x0F48
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT0_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0 */
+#define EUR_CR_BREAKPOINT0                  0x0F4C
+#define EUR_CR_BREAKPOINT0_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT0_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT0_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT0_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_START */
+#define EUR_CR_BREAKPOINT1_START            0x0F50
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT1_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_END */
+#define EUR_CR_BREAKPOINT1_END              0x0F54
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT1_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1 */
+#define EUR_CR_BREAKPOINT1                  0x0F58
+#define EUR_CR_BREAKPOINT1_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT1_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT1_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT1_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT1_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_START */
+#define EUR_CR_BREAKPOINT2_START            0x0F5C
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT2_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_END */
+#define EUR_CR_BREAKPOINT2_END              0x0F60
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT2_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2 */
+#define EUR_CR_BREAKPOINT2                  0x0F64
+#define EUR_CR_BREAKPOINT2_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT2_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT2_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT2_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT2_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_START */
+#define EUR_CR_BREAKPOINT3_START            0x0F68
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT3_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_END */
+#define EUR_CR_BREAKPOINT3_END              0x0F6C
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT3_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3 */
+#define EUR_CR_BREAKPOINT3                  0x0F70
+#define EUR_CR_BREAKPOINT3_MASK_DM_MASK     0x00000038U
+#define EUR_CR_BREAKPOINT3_MASK_DM_SHIFT    3
+#define EUR_CR_BREAKPOINT3_MASK_DM_SIGNED   0
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_MASK 0x00000004U
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_SHIFT 2
+#define EUR_CR_BREAKPOINT3_CTRL_TRAPENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_MASK 0x00000002U
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_SHIFT 1
+#define EUR_CR_BREAKPOINT3_CTRL_WENABLE_SIGNED 0
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_MASK 0x00000001U
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SHIFT 0
+#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT_READ */
+#define EUR_CR_BREAKPOINT_READ              0x0F74
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_SHIFT 4
+#define EUR_CR_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP */
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP    0x0F78
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT */
+#define EUR_CR_PARTITION_BREAKPOINT         0x0F7C
+#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
+#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_SHIFT 6
+#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_ID_MASK 0x00000030U
+#define EUR_CR_PARTITION_BREAKPOINT_ID_SHIFT 4
+#define EUR_CR_PARTITION_BREAKPOINT_ID_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_UNTRAPPED_MASK 0x00000008U
+#define EUR_CR_PARTITION_BREAKPOINT_UNTRAPPED_SHIFT 3
+#define EUR_CR_PARTITION_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_MASK 0x00000004U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SHIFT 2
+#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 0x0F80
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 0x0F84
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_0 */
+#define EUR_CR_USE_CODE_BASE_0              0x0A0C
+#define EUR_CR_USE_CODE_BASE_ADDR_00_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_00_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_00_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_00_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_1 */
+#define EUR_CR_USE_CODE_BASE_1              0x0A10
+#define EUR_CR_USE_CODE_BASE_ADDR_01_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_01_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_01_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_01_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_2 */
+#define EUR_CR_USE_CODE_BASE_2              0x0A14
+#define EUR_CR_USE_CODE_BASE_ADDR_02_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_02_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_02_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_02_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_3 */
+#define EUR_CR_USE_CODE_BASE_3              0x0A18
+#define EUR_CR_USE_CODE_BASE_ADDR_03_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_03_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_03_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_03_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_4 */
+#define EUR_CR_USE_CODE_BASE_4              0x0A1C
+#define EUR_CR_USE_CODE_BASE_ADDR_04_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_04_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_04_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_04_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_5 */
+#define EUR_CR_USE_CODE_BASE_5              0x0A20
+#define EUR_CR_USE_CODE_BASE_ADDR_05_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_05_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_05_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_05_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_6 */
+#define EUR_CR_USE_CODE_BASE_6              0x0A24
+#define EUR_CR_USE_CODE_BASE_ADDR_06_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_06_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_06_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_06_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_7 */
+#define EUR_CR_USE_CODE_BASE_7              0x0A28
+#define EUR_CR_USE_CODE_BASE_ADDR_07_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_07_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_07_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_07_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_8 */
+#define EUR_CR_USE_CODE_BASE_8              0x0A2C
+#define EUR_CR_USE_CODE_BASE_ADDR_08_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_08_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_08_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_08_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_9 */
+#define EUR_CR_USE_CODE_BASE_9              0x0A30
+#define EUR_CR_USE_CODE_BASE_ADDR_09_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_09_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_09_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_09_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_10 */
+#define EUR_CR_USE_CODE_BASE_10             0x0A34
+#define EUR_CR_USE_CODE_BASE_ADDR_10_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_10_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_10_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_10_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_11 */
+#define EUR_CR_USE_CODE_BASE_11             0x0A38
+#define EUR_CR_USE_CODE_BASE_ADDR_11_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_11_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_11_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_11_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_12 */
+#define EUR_CR_USE_CODE_BASE_12             0x0A3C
+#define EUR_CR_USE_CODE_BASE_ADDR_12_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_12_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_12_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_12_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_13 */
+#define EUR_CR_USE_CODE_BASE_13             0x0A40
+#define EUR_CR_USE_CODE_BASE_ADDR_13_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_13_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_13_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_13_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_14 */
+#define EUR_CR_USE_CODE_BASE_14             0x0A44
+#define EUR_CR_USE_CODE_BASE_ADDR_14_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_14_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_14_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_14_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_15 */
+#define EUR_CR_USE_CODE_BASE_15             0x0A48
+#define EUR_CR_USE_CODE_BASE_ADDR_15_MASK   0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_15_MASK     0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_15_SHIFT    26
+#define EUR_CR_USE_CODE_BASE_DM_15_SIGNED   0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP */
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP        0x0F88
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT */
+#define EUR_CR_PIPE0_BREAKPOINT             0x0F8C
+#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
+#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_SHIFT 6
+#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_ID_MASK     0x00000030U
+#define EUR_CR_PIPE0_BREAKPOINT_ID_SHIFT    4
+#define EUR_CR_PIPE0_BREAKPOINT_ID_SIGNED   0
+#define EUR_CR_PIPE0_BREAKPOINT_UNTRAPPED_MASK 0x00000008U
+#define EUR_CR_PIPE0_BREAKPOINT_UNTRAPPED_SHIFT 3
+#define EUR_CR_PIPE0_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_MASK 0x00000004U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SHIFT 2
+#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0  0x0F90
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1  0x0F94
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP */
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP        0x0F98
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT */
+#define EUR_CR_PIPE1_BREAKPOINT             0x0F9C
+#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
+#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_SHIFT 6
+#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_ID_MASK     0x00000030U
+#define EUR_CR_PIPE1_BREAKPOINT_ID_SHIFT    4
+#define EUR_CR_PIPE1_BREAKPOINT_ID_SIGNED   0
+#define EUR_CR_PIPE1_BREAKPOINT_UNTRAPPED_MASK 0x00000008U
+#define EUR_CR_PIPE1_BREAKPOINT_UNTRAPPED_SHIFT 3
+#define EUR_CR_PIPE1_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_MASK 0x00000004U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SHIFT 2
+#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0  0x0FA0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1  0x0FA4
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x03FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_ADDR_SIGNED    0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x0C000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       26
+#define EUR_CR_USE_CODE_BASE_DM_SIGNED      0
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX544DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx545defs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx545defs.h
new file mode 100644
index 0000000..c5adee2
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgx545defs.h
@@ -0,0 +1,1290 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGX545.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGX545DEFS_KM_H_
+#define _SGX545DEFS_KM_H_
+
+/* Register EUR_CR_CLKGATECTL */
+#define EUR_CR_CLKGATECTL                   0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK     0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT    0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK    0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT   2
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK     0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT    4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK      0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT     6
+#define EUR_CR_CLKGATECTL_TE_CLKG_SIGNED    0
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK     0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT    8
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK     0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT    10
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK     0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT    12
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SIGNED   0
+#define EUR_CR_CLKGATECTL_PDS0_CLKG_MASK    0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS0_CLKG_SHIFT   14
+#define EUR_CR_CLKGATECTL_PDS0_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SIGNED 0
+/* Register EUR_CR_CLKGATECTL2 */
+#define EUR_CR_CLKGATECTL2                  0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK    0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT   0
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SIGNED  0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT  6
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK   0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT  8
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK   0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT  10
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK  0x00003000U
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK   0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT  14
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK   0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT  16
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK   0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT  18
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK  0x00300000U
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SIGNED 0
+#define EUR_CR_CLKGATECTL2_PDS1_CLKG_MASK   0x00C00000U
+#define EUR_CR_CLKGATECTL2_PDS1_CLKG_SHIFT  22
+#define EUR_CR_CLKGATECTL2_PDS1_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATESTATUS */
+#define EUR_CR_CLKGATESTATUS                0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK  0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK  0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK   0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT  3
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK  0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK  0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK  0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PDS0_CLKS_MASK 0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS0_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PDS0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK  0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000U
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000U
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SIGNED 0
+#define EUR_CR_CLKGATESTATUS_PDS1_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_PDS1_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_PDS1_CLKS_SIGNED 0
+/* Register EUR_CR_CLKGATECTLOVR */
+#define EUR_CR_CLKGATECTLOVR                0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK  0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK  0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK   0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT  6
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK  0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK  0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK  0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SIGNED 0
+#define EUR_CR_CLKGATECTLOVR_PDS0_CLKO_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS0_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_PDS0_CLKO_SIGNED 0
+/* Register EUR_CR_CORE_ID */
+#define EUR_CR_CORE_ID                      0x001C
+#define EUR_CR_CORE_ID_CONFIG_MASK          0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT         0
+#define EUR_CR_CORE_ID_CONFIG_SIGNED        0
+#define EUR_CR_CORE_ID_ID_MASK              0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT             16
+#define EUR_CR_CORE_ID_ID_SIGNED            0
+/* Register EUR_CR_CORE_REVISION */
+#define EUR_CR_CORE_REVISION                0x0020
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SIGNED 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK     0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT    8
+#define EUR_CR_CORE_REVISION_MINOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_MAJOR_MASK     0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT    16
+#define EUR_CR_CORE_REVISION_MAJOR_SIGNED   0
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK  0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
+#define EUR_CR_DESIGNER_REV_FIELD1          0x0024
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
+#define EUR_CR_DESIGNER_REV_FIELD2          0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SIGNED 0
+/* Register EUR_CR_SOFT_RESET */
+#define EUR_CR_SOFT_RESET                   0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK    0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT   0
+#define EUR_CR_SOFT_RESET_BIF_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK    0x00000002U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT   1
+#define EUR_CR_SOFT_RESET_DPM_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK     0x00000004U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT    2
+#define EUR_CR_SOFT_RESET_TA_RESET_SIGNED   0
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK    0x00000008U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT   3
+#define EUR_CR_SOFT_RESET_USE_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK    0x00000010U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT   4
+#define EUR_CR_SOFT_RESET_ISP_RESET_SIGNED  0
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK    0x00000020U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT   5
+#define EUR_CR_SOFT_RESET_TSP_RESET_SIGNED  0
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
+#define EUR_CR_EVENT_HOST_ENABLE2           0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_CONTEXT_LOAD_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_CONTEXT_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_TASK_KICKED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE2_VDM_TASK_KICKED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_MEM_CLEARED_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_MEM_CLEARED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_FLUSHED_INV_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE2_OTPM_FLUSHED_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_FLUSHED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_LOADED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE2_GSG_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
+#define EUR_CR_EVENT_HOST_CLEAR2            0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_CONTEXT_LOAD_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_CONTEXT_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_TASK_KICKED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR2_VDM_TASK_KICKED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_MEM_CLEARED_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_MEM_CLEARED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_FLUSHED_INV_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR2_OTPM_FLUSHED_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_FLUSHED_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_LOADED_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR2_GSG_LOADED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS2 */
+#define EUR_CR_EVENT_STATUS2                0x0118
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SHIFT 15
+#define EUR_CR_EVENT_STATUS2_MTE_STATE_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_VDM_CONTEXT_LOAD_MASK 0x00004000U
+#define EUR_CR_EVENT_STATUS2_VDM_CONTEXT_LOAD_SHIFT 14
+#define EUR_CR_EVENT_STATUS2_VDM_CONTEXT_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_VDM_TASK_KICKED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS2_VDM_TASK_KICKED_SHIFT 13
+#define EUR_CR_EVENT_STATUS2_VDM_TASK_KICKED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_OTPM_MEM_CLEARED_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS2_OTPM_MEM_CLEARED_SHIFT 12
+#define EUR_CR_EVENT_STATUS2_OTPM_MEM_CLEARED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_OTPM_FLUSHED_INV_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS2_OTPM_FLUSHED_INV_SHIFT 11
+#define EUR_CR_EVENT_STATUS2_OTPM_FLUSHED_INV_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SHIFT 10
+#define EUR_CR_EVENT_STATUS2_DCU_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_GSG_FLUSHED_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS2_GSG_FLUSHED_SHIFT 9
+#define EUR_CR_EVENT_STATUS2_GSG_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_GSG_LOADED_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS2_GSG_LOADED_SHIFT 8
+#define EUR_CR_EVENT_STATUS2_GSG_LOADED_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK   0x00000080U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT  7
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK   0x00000040U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT  6
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK   0x00000020U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT  5
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS */
+#define EUR_CR_EVENT_STATUS                 0x012C
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TIMER_MASK      0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT     29
+#define EUR_CR_EVENT_STATUS_TIMER_SIGNED    0
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_STATUS_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK   0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT  20
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SIGNED 0
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK   0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT  14
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK  0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK  0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
+#define EUR_CR_EVENT_HOST_ENABLE            0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
+#define EUR_CR_EVENT_HOST_CLEAR             0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK  0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_ISP2_ZLS_CSW_FINISHED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP2_ZLS_CSW_FINISHED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_ISP2_ZLS_CSW_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SIGNED 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_TIMER */
+#define EUR_CR_TIMER                        0x0144
+#define EUR_CR_TIMER_VALUE_MASK             0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT            0
+#define EUR_CR_TIMER_VALUE_SIGNED           0
+/* Register EUR_CR_USE_CODE_BASE_0 */
+#define EUR_CR_USE_CODE_BASE_0              0x0A0C
+#define EUR_CR_USE_CODE_BASE_ADDR_00_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_00_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_00_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_00_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_00_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_1 */
+#define EUR_CR_USE_CODE_BASE_1              0x0A10
+#define EUR_CR_USE_CODE_BASE_ADDR_01_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_01_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_01_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_01_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_01_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_2 */
+#define EUR_CR_USE_CODE_BASE_2              0x0A14
+#define EUR_CR_USE_CODE_BASE_ADDR_02_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_02_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_02_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_02_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_02_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_3 */
+#define EUR_CR_USE_CODE_BASE_3              0x0A18
+#define EUR_CR_USE_CODE_BASE_ADDR_03_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_03_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_03_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_03_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_03_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_4 */
+#define EUR_CR_USE_CODE_BASE_4              0x0A1C
+#define EUR_CR_USE_CODE_BASE_ADDR_04_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_04_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_04_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_04_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_04_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_5 */
+#define EUR_CR_USE_CODE_BASE_5              0x0A20
+#define EUR_CR_USE_CODE_BASE_ADDR_05_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_05_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_05_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_05_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_05_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_6 */
+#define EUR_CR_USE_CODE_BASE_6              0x0A24
+#define EUR_CR_USE_CODE_BASE_ADDR_06_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_06_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_06_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_06_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_06_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_7 */
+#define EUR_CR_USE_CODE_BASE_7              0x0A28
+#define EUR_CR_USE_CODE_BASE_ADDR_07_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_07_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_07_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_07_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_07_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_8 */
+#define EUR_CR_USE_CODE_BASE_8              0x0A2C
+#define EUR_CR_USE_CODE_BASE_ADDR_08_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_08_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_08_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_08_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_08_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_9 */
+#define EUR_CR_USE_CODE_BASE_9              0x0A30
+#define EUR_CR_USE_CODE_BASE_ADDR_09_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_09_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_09_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_09_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_09_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_10 */
+#define EUR_CR_USE_CODE_BASE_10             0x0A34
+#define EUR_CR_USE_CODE_BASE_ADDR_10_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_10_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_10_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_10_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_10_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_11 */
+#define EUR_CR_USE_CODE_BASE_11             0x0A38
+#define EUR_CR_USE_CODE_BASE_ADDR_11_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_11_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_11_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_11_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_11_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_12 */
+#define EUR_CR_USE_CODE_BASE_12             0x0A3C
+#define EUR_CR_USE_CODE_BASE_ADDR_12_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_12_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_12_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_12_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_12_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_13 */
+#define EUR_CR_USE_CODE_BASE_13             0x0A40
+#define EUR_CR_USE_CODE_BASE_ADDR_13_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_13_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_13_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_13_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_13_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_14 */
+#define EUR_CR_USE_CODE_BASE_14             0x0A44
+#define EUR_CR_USE_CODE_BASE_ADDR_14_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_14_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_14_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_14_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_14_SIGNED   0
+/* Register EUR_CR_USE_CODE_BASE_15 */
+#define EUR_CR_USE_CODE_BASE_15             0x0A48
+#define EUR_CR_USE_CODE_BASE_ADDR_15_MASK   0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SHIFT  0
+#define EUR_CR_USE_CODE_BASE_ADDR_15_SIGNED 0
+#define EUR_CR_USE_CODE_BASE_DM_15_MASK     0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_15_SHIFT    25
+#define EUR_CR_USE_CODE_BASE_DM_15_SIGNED   0
+/* Register EUR_CR_PDS_EXEC_BASE */
+#define EUR_CR_PDS_EXEC_BASE                0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK      0xFFF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT     20
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SIGNED    0
+/* Register EUR_CR_EVENT_KICKER */
+#define EUR_CR_EVENT_KICKER                 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK    0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT   4
+#define EUR_CR_EVENT_KICKER_ADDRESS_SIGNED  0
+/* Register EUR_CR_EVENT_KICK */
+#define EUR_CR_EVENT_KICK                   0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK          0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT         0
+#define EUR_CR_EVENT_KICK_NOW_SIGNED        0
+/* Register EUR_CR_EVENT_TIMER */
+#define EUR_CR_EVENT_TIMER                  0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK      0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT     24
+#define EUR_CR_EVENT_TIMER_ENABLE_SIGNED    0
+#define EUR_CR_EVENT_TIMER_VALUE_MASK       0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT      0
+#define EUR_CR_EVENT_TIMER_VALUE_SIGNED     0
+/* Register EUR_CR_PDS_INV0 */
+#define EUR_CR_PDS_INV0                     0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT           0
+#define EUR_CR_PDS_INV0_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV1 */
+#define EUR_CR_PDS_INV1                     0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT           0
+#define EUR_CR_PDS_INV1_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV3 */
+#define EUR_CR_PDS_INV3                     0x0AD8
+#define EUR_CR_PDS_INV3_DSC_MASK            0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT           0
+#define EUR_CR_PDS_INV3_DSC_SIGNED          0
+/* Register EUR_CR_PDS_INV_CSC */
+#define EUR_CR_PDS_INV_CSC                  0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK        0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT       0
+#define EUR_CR_PDS_INV_CSC_KICK_SIGNED      0
+/* Register EUR_CR_EVENT_KICK1 */
+#define EUR_CR_EVENT_KICK1                  0x0AE4
+#define EUR_CR_EVENT_KICK1_NOW_MASK         0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK1_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICK2 */
+#define EUR_CR_EVENT_KICK2                  0x0AE8
+#define EUR_CR_EVENT_KICK2_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK2_NOW_SIGNED       0
+/* Register EUR_CR_EVENT_KICK3 */
+#define EUR_CR_EVENT_KICK3                  0x0AEC
+#define EUR_CR_EVENT_KICK3_NOW_MASK         0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT        0
+#define EUR_CR_EVENT_KICK3_NOW_SIGNED       0
+/* Register EUR_CR_BIF_CTRL */
+#define EUR_CR_BIF_CTRL                     0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK      0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT     0
+#define EUR_CR_BIF_CTRL_NOREORDER_SIGNED    0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK          0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT         1
+#define EUR_CR_BIF_CTRL_PAUSE_SIGNED        0
+#define EUR_CR_BIF_CTRL_FLUSH_MASK          0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT         2
+#define EUR_CR_BIF_CTRL_FLUSH_SIGNED        0
+#define EUR_CR_BIF_CTRL_INVALDC_MASK        0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT       3
+#define EUR_CR_BIF_CTRL_INVALDC_SIGNED      0
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK    0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT   4
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SIGNED  0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK  0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00000800U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SIGNED 0
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SIGNED 0
+/* Register EUR_CR_BIF_INT_STAT */
+#define EUR_CR_BIF_INT_STAT                 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK  0x0000FFFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_MASK 0x00070000U
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SHIFT 16
+#define EUR_CR_BIF_INT_STAT_FAULT_TYPE_SIGNED 0
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SIGNED 0
+/* Register EUR_CR_BIF_FAULT */
+#define EUR_CR_BIF_FAULT                    0x0C08
+#define EUR_CR_BIF_FAULT_CID_MASK           0x0000000FU
+#define EUR_CR_BIF_FAULT_CID_SHIFT          0
+#define EUR_CR_BIF_FAULT_CID_SIGNED         0
+#define EUR_CR_BIF_FAULT_SB_MASK            0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT           4
+#define EUR_CR_BIF_FAULT_SB_SIGNED          0
+#define EUR_CR_BIF_FAULT_ADDR_MASK          0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT         12
+#define EUR_CR_BIF_FAULT_ADDR_SIGNED        0
+/* Register EUR_CR_BIF_TILE0 */
+#define EUR_CR_BIF_TILE0                    0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE0_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE0_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE1 */
+#define EUR_CR_BIF_TILE1                    0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE1_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE1_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE2 */
+#define EUR_CR_BIF_TILE2                    0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE2_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE2_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE3 */
+#define EUR_CR_BIF_TILE3                    0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE3_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE3_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE4 */
+#define EUR_CR_BIF_TILE4                    0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE4_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE4_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE5 */
+#define EUR_CR_BIF_TILE5                    0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE5_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE5_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE6 */
+#define EUR_CR_BIF_TILE6                    0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE6_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE6_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE7 */
+#define EUR_CR_BIF_TILE7                    0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE7_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE7_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE8 */
+#define EUR_CR_BIF_TILE8                    0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE8_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE8_CFG_SIGNED         0
+/* Register EUR_CR_BIF_TILE9 */
+#define EUR_CR_BIF_TILE9                    0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK   0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT  0
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK   0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT  12
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SIGNED 0
+#define EUR_CR_BIF_TILE9_CFG_MASK           0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT          24
+#define EUR_CR_BIF_TILE9_CFG_SIGNED         0
+/* Register EUR_CR_BIF_DIR_LIST_BASE1 */
+#define EUR_CR_BIF_DIR_LIST_BASE1           0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE2 */
+#define EUR_CR_BIF_DIR_LIST_BASE2           0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE3 */
+#define EUR_CR_BIF_DIR_LIST_BASE3           0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE4 */
+#define EUR_CR_BIF_DIR_LIST_BASE4           0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE5 */
+#define EUR_CR_BIF_DIR_LIST_BASE5           0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE6 */
+#define EUR_CR_BIF_DIR_LIST_BASE6           0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE7 */
+#define EUR_CR_BIF_DIR_LIST_BASE7           0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE8 */
+#define EUR_CR_BIF_DIR_LIST_BASE8           0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE9 */
+#define EUR_CR_BIF_DIR_LIST_BASE9           0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE10 */
+#define EUR_CR_BIF_DIR_LIST_BASE10          0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE11 */
+#define EUR_CR_BIF_DIR_LIST_BASE11          0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE12 */
+#define EUR_CR_BIF_DIR_LIST_BASE12          0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE13 */
+#define EUR_CR_BIF_DIR_LIST_BASE13          0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE14 */
+#define EUR_CR_BIF_DIR_LIST_BASE14          0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE15 */
+#define EUR_CR_BIF_DIR_LIST_BASE15          0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_SET */
+#define EUR_CR_BIF_BANK_SET                 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK  0x00000001U
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
+#define EUR_CR_BIF_BANK_SET_SELECT_2D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_MASK  0x0000000CU
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SHIFT 2
+#define EUR_CR_BIF_BANK_SET_SELECT_3D_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_MASK 0x00000010U
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SHIFT 4
+#define EUR_CR_BIF_BANK_SET_SELECT_HOST_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_MASK  0x000000C0U
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SHIFT 6
+#define EUR_CR_BIF_BANK_SET_SELECT_TA_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_MASK 0x00000100U
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SHIFT 8
+#define EUR_CR_BIF_BANK_SET_SELECT_EDM_SIGNED 0
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200U
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
+#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SIGNED 0
+/* Register EUR_CR_BIF_BANK0 */
+#define EUR_CR_BIF_BANK0                    0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK0_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK    0x00000F00U
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SIGNED  0
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK0_INDEX_3D_SIGNED    0
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK      0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_BANK0_INDEX_2D_SIGNED    0
+/* Register EUR_CR_BIF_BANK1 */
+#define EUR_CR_BIF_BANK1                    0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK     0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT    0
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SIGNED   0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK      0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT     4
+#define EUR_CR_BIF_BANK1_INDEX_TA_SIGNED    0
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK    0x00000F00U
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT   8
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SIGNED  0
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK      0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT     12
+#define EUR_CR_BIF_BANK1_INDEX_3D_SIGNED    0
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK      0x000F0000U
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT     16
+#define EUR_CR_BIF_BANK1_INDEX_2D_SIGNED    0
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
+#define EUR_CR_BIF_DIR_LIST_BASE0           0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFFF00U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 8
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TA_REQ_BASE */
+#define EUR_CR_BIF_TA_REQ_BASE              0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
+#define EUR_CR_BIF_MEM_REQ_STAT             0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK  0x000007FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SIGNED 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
+#define EUR_CR_BIF_3D_REQ_BASE              0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK    0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT   20
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SIGNED  0
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
+#define EUR_CR_BIF_ZLS_REQ_BASE             0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK   0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT  20
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_STATUS */
+#define EUR_CR_BIF_BANK_STATUS              0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SIGNED 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SIGNED 0
+/* Register EUR_CR_BIF_36BIT_ADDRESSING */
+#define EUR_CR_BIF_36BIT_ADDRESSING         0x0CCC
+#define EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK 0x00000001U
+#define EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_SHIFT 0
+#define EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_SIGNED 0
+/* Register EUR_CR_BIF_TILE0_ADDR_EXT */
+#define EUR_CR_BIF_TILE0_ADDR_EXT           0x0CD0
+#define EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE1_ADDR_EXT */
+#define EUR_CR_BIF_TILE1_ADDR_EXT           0x0CD4
+#define EUR_CR_BIF_TILE1_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE1_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE1_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE1_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE1_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE1_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE2_ADDR_EXT */
+#define EUR_CR_BIF_TILE2_ADDR_EXT           0x0CD8
+#define EUR_CR_BIF_TILE2_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE2_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE2_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE2_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE2_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE2_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE3_ADDR_EXT */
+#define EUR_CR_BIF_TILE3_ADDR_EXT           0x0CDC
+#define EUR_CR_BIF_TILE3_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE3_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE3_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE3_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE3_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE3_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE4_ADDR_EXT */
+#define EUR_CR_BIF_TILE4_ADDR_EXT           0x0CE0
+#define EUR_CR_BIF_TILE4_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE4_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE4_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE4_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE4_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE4_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE5_ADDR_EXT */
+#define EUR_CR_BIF_TILE5_ADDR_EXT           0x0CE4
+#define EUR_CR_BIF_TILE5_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE5_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE5_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE5_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE5_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE5_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE6_ADDR_EXT */
+#define EUR_CR_BIF_TILE6_ADDR_EXT           0x0CE8
+#define EUR_CR_BIF_TILE6_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE6_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE6_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE6_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE6_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE6_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE7_ADDR_EXT */
+#define EUR_CR_BIF_TILE7_ADDR_EXT           0x0CEC
+#define EUR_CR_BIF_TILE7_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE7_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE7_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE7_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE7_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE7_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE8_ADDR_EXT */
+#define EUR_CR_BIF_TILE8_ADDR_EXT           0x0CF0
+#define EUR_CR_BIF_TILE8_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE8_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE8_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE8_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE8_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE8_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_TILE9_ADDR_EXT */
+#define EUR_CR_BIF_TILE9_ADDR_EXT           0x0CF4
+#define EUR_CR_BIF_TILE9_ADDR_EXT_MIN_MASK  0x000000FFU
+#define EUR_CR_BIF_TILE9_ADDR_EXT_MIN_SHIFT 0
+#define EUR_CR_BIF_TILE9_ADDR_EXT_MIN_SIGNED 0
+#define EUR_CR_BIF_TILE9_ADDR_EXT_MAX_MASK  0x0000FF00U
+#define EUR_CR_BIF_TILE9_ADDR_EXT_MAX_SHIFT 8
+#define EUR_CR_BIF_TILE9_ADDR_EXT_MAX_SIGNED 0
+/* Register EUR_CR_BIF_CTRL_RDATA */
+#define EUR_CR_BIF_CTRL_RDATA               0x0CF8
+#define EUR_CR_BIF_CTRL_RDATA_LIMIT_MASK    0x000003FFU
+#define EUR_CR_BIF_CTRL_RDATA_LIMIT_SHIFT   0
+#define EUR_CR_BIF_CTRL_RDATA_LIMIT_SIGNED  0
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE(X)     (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK      0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT     0
+#define EUR_CR_USE_CODE_BASE_ADDR_SIGNED    0
+#define EUR_CR_USE_CODE_BASE_DM_MASK        0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT       25
+#define EUR_CR_USE_CODE_BASE_DM_SIGNED      0
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif /* _SGX545DEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxdefs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxdefs.h
new file mode 100644
index 0000000..7acba79
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxdefs.h
@@ -0,0 +1,116 @@
+/*************************************************************************/ /*!
+@Title          SGX hw definitions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGXDEFS_H_
+#define	_SGXDEFS_H_
+
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#if defined(SGX520)
+#include "sgx520defs.h"
+#else
+#if defined(SGX5300)
+#include "sgx5300defs.h"
+#else
+#if defined(SGX530)
+#include "sgx530defs.h"
+#else
+#if defined(SGX535)
+#include "sgx535defs.h"
+#else
+#if defined(SGX535_V1_1)
+#include "sgx535defs.h"
+#else
+#if defined(SGX540)
+#include "sgx540defs.h"
+#else
+#if defined(SGX543)
+#if defined(FIX_HW_BRN_29954)
+#include "sgx543_v1.164defs.h"
+#else
+#include "sgx543defs.h"
+#endif
+#else
+#if defined(SGX544)
+#include "sgx544defs.h"
+#else
+#if defined(SGX545)
+#include "sgx545defs.h"
+#else
+#if defined(SGX531)
+#include "sgx531defs.h"
+#else
+#if defined(SGX554)
+#include "sgx554defs.h"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX554)
+#include "sgxmpplusdefs.h"
+#else
+#include "sgxmpdefs.h"
+#endif /* SGX554 */
+#else /* SGX_FEATURE_MP */
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#include "mnemedefs.h"
+#endif
+#endif /* SGX_FEATURE_MP */
+
+/*****************************************************************************
+ Core specific defines.
+*****************************************************************************/
+
+#endif /* _SGXDEFS_H_ */
+
+/*****************************************************************************
+ End of file (sgxdefs.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxerrata.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxerrata.h
new file mode 100644
index 0000000..e423d4f
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxerrata.h
@@ -0,0 +1,484 @@
+/*************************************************************************/ /*!
+@Title          SGX HW errata definitions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Specifies associations between SGX core revisions
+                and SW workarounds required to fix HW errata that exist
+                in specific core revisions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef _SGXERRATA_KM_H_
+#define _SGXERRATA_KM_H_
+
+/* ignore warnings about unrecognised preprocessing directives in conditional inclusion directives */
+/* PRQA S 3115 ++ */
+
+#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX520 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 111
+	#else
+	#if SGX_CORE_REV == 112
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		/* RTL head - no BRNs to apply */
+	#else
+		#error "sgxerrata.h: SGX520 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX5300) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX5300 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 112
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		/* RTL head - no BRNs to apply */
+	#else
+		#error "sgxerrata.h: SGX5300 Core Revision unspecified"
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+
+#endif
+
+#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX530 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 120
+		#define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */	
+		#define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == 121
+		#define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */	
+		#define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == 125
+		#define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */	
+		#define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == 130
+		#define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */	
+		#define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		/* RTL head - no BRNs to apply */
+	#else
+		#error "sgxerrata.h: SGX530 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+#endif
+        #endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX531 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 110
+		#define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		/* RTL head - no BRNs to apply */
+	#else
+		#error "sgxerrata.h: SGX531 Core Revision unspecified"
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX535 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 121
+		#define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */	
+		#define FIX_HW_BRN_23944/* Workaround in code (services) */
+		#define FIX_HW_BRN_23410/* Workaround in code (services) and ucode */
+	#else
+	#if SGX_CORE_REV == 126
+		#define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */	
+	#else	
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		/* RTL head - no BRNs to apply */
+	#else
+		#error "sgxerrata.h: SGX535 Core Revision unspecified"
+
+	#endif
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX540 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 120
+		#define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+		#define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+		#define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == 121
+		#define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+		#define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == 130
+		#define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		/* RTL head - no BRNs to apply */
+	#else
+		#error "sgxerrata.h: SGX540 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+
+#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX543 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 122
+		#define FIX_HW_BRN_29954/* turns off regbank split feature */
+		#define FIX_HW_BRN_29997/* workaround in services */
+		#define FIX_HW_BRN_30954/* workaround in services */
+		#define FIX_HW_BRN_31093/* workaround in services */
+		#define FIX_HW_BRN_31195/* workaround in services */
+		#define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+		#define FIX_HW_BRN_31278/* disabled prefetching in MMU */
+		#define FIX_HW_BRN_31542/* workaround in uKernel and Services */
+		#define FIX_HW_BRN_31620/* workaround in services */
+		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+		#define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_33920/* workaround in ukernel */
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+			/* add BRNs here */
+	#else
+	#if SGX_CORE_REV == 1221
+		#define FIX_HW_BRN_29954/* turns off regbank split feature */
+        #define FIX_HW_BRN_31195/* workaround in services */
+		#define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+		#define FIX_HW_BRN_31278/* disabled prefetching in MMU */
+		#define FIX_HW_BRN_31542/* workaround in uKernel and Services */
+		#define FIX_HW_BRN_31671/* workaround in uKernel */		
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#define FIX_HW_BRN_32044/* workaround in uKernel, services and client drivers */
+		#define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_33920/* workaround in ukernel */
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+			/* add BRNs here */
+	#else
+	#if SGX_CORE_REV == 141
+		#define FIX_HW_BRN_29954/* turns off regbank split feature */
+		#define FIX_HW_BRN_31671 /* workaround in uKernel */
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+			/* add BRNs here */
+	#else
+	#if SGX_CORE_REV == 142
+		#define FIX_HW_BRN_29954/* turns off regbank split feature */
+		#define FIX_HW_BRN_31671 /* workaround in uKernel */
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+			/* add BRNs here */
+	#else
+	#if SGX_CORE_REV == 213
+		#define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+		#define FIX_HW_BRN_31671 /* workaround in uKernel */
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_33920/* workaround in ukernel */
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+			/* add BRNs here */
+	#else
+	#if SGX_CORE_REV == 216
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else
+	#if SGX_CORE_REV == 303
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+		#if defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_43863 /* Workaround in ukernel */
+		#endif
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+	#else
+		#error "sgxerrata.h: SGX543 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX544) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX544 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 104
+		#define FIX_HW_BRN_29954/* turns off regbank split feature */
+		#define FIX_HW_BRN_31093/* workaround in services */
+		#define FIX_HW_BRN_31195/* workaround in services */
+		#define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+		#define FIX_HW_BRN_31278/* disabled prefetching in MMU */
+		#define FIX_HW_BRN_31542 /* workaround in uKernel and Services */
+ 		#define FIX_HW_BRN_31620/* workaround in services */
+		#define FIX_HW_BRN_31671 /* workaround in uKernel */
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+		#define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_33920/* workaround in ukernel */
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else	
+	#if SGX_CORE_REV == 105
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_33920/* workaround in ukernel */
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else
+	#if SGX_CORE_REV == 112
+		#define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+		#define FIX_HW_BRN_33920/* workaround in ukernel */
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else
+	#if SGX_CORE_REV == 114
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+	#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else
+	#if SGX_CORE_REV == 115
+ 		#define FIX_HW_BRN_31780/* workaround in uKernel */
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else
+	#if SGX_CORE_REV == 116
+		#if defined(SGX_FEATURE_MP)
+			#if SGX_FEATURE_MP_CORE_COUNT == 1	
+				#define FIX_HW_BRN_33809/* workaround in kernel (enable burst combiner) */
+			#endif
+		#endif
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel */
+		#endif
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else
+	#if SGX_CORE_REV == 117
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel */
+		#endif
+		#define FIX_HW_BRN_33809/* workaround in kernel (enable burst combiner) */
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+	#else
+	#if SGX_CORE_REV == 118
+		#define FIX_HW_BRN_33920/* workaround in ukernel */
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+	#else
+		#error "sgxerrata.h: SGX544 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX545 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 10131
+	#else
+	#if SGX_CORE_REV == 1014
+	#else
+	#if SGX_CORE_REV == 10141
+	#else
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		/* RTL head - no BRNs to apply */
+	#else
+		#error "sgxerrata.h: SGX545 Core Revision unspecified"
+	#endif
+	#endif
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX554) && !defined(SGX_CORE_DEFINED)
+	/* define the _current_ SGX554 RTL head revision */
+	#define SGX_CORE_REV_HEAD	0
+	#if defined(USE_SGX_CORE_REV_HEAD)
+		/* build config selects Core Revision to be the Head */
+		#define SGX_CORE_REV	SGX_CORE_REV_HEAD
+	#endif
+
+	#if SGX_CORE_REV == 1251
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+		#define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+		/* add BRNs here */
+	#else	
+	#if SGX_CORE_REV == SGX_CORE_REV_HEAD
+		#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+			#define FIX_HW_BRN_33657/* workaround in ukernel*/
+		#endif
+	#else
+		#error "sgxerrata.h: SGX554 Core Revision unspecified"
+	#endif
+	#endif
+	/* signal that the Core Version has a valid definition */
+	#define SGX_CORE_DEFINED
+#endif
+
+#if !defined(SGX_CORE_DEFINED)
+#if defined (__GNUC__)
+	#warning "sgxerrata.h: SGX Core Version unspecified"
+#else
+	#pragma message("sgxerrata.h: SGX Core Version unspecified")
+#endif
+#endif
+
+/* restore warning */
+/* PRQA S 3115 -- */
+
+#endif /* _SGXERRATA_KM_H_ */
+
+/******************************************************************************
+ End of file (sgxerrata.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
new file mode 100644
index 0000000..de07cc8
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxfeaturedefs.h
@@ -0,0 +1,290 @@
+/*************************************************************************/ /*!
+@Title          SGX fexture definitions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#if defined(SGX520)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX520"
+	#define SGX_CORE_ID										SGX_CORE_ID_520
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_NUM_USE_PIPES						(1)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(1)
+#else
+#if defined(SGX5300)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX5300"
+	#define SGX_CORE_ID										SGX_CORE_ID_5300
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_ADDRESS_SPACE_EXTENSION
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(16)
+	#define SGX_FEATURE_NUM_USE_PIPES						(1)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(1)
+#else
+#if defined(SGX530)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX530"
+	#define SGX_CORE_ID										SGX_CORE_ID_530
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_NUM_USE_PIPES						(2)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(1)
+#else
+#if defined(SGX531)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX531"
+	#define SGX_CORE_ID										SGX_CORE_ID_531
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_NUM_USE_PIPES						(2)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(1)
+#else
+#if defined(SGX535)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX535"
+	#define SGX_CORE_ID										SGX_CORE_ID_535
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(16)
+	#define SGX_FEATURE_2D_HARDWARE
+	#define SGX_FEATURE_NUM_USE_PIPES						(2)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SUPPORT_SGX_GENERAL_MAPPING_HEAP
+	#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(1)
+#else
+#if defined(SGX540)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX540"
+	#define SGX_CORE_ID										SGX_CORE_ID_540
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(28)
+	#define SGX_FEATURE_NUM_USE_PIPES						(4)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(1)
+#else
+#if defined(SGX543)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX543"
+	#define SGX_CORE_ID										SGX_CORE_ID_543
+	#define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+	#define SGX_FEATURE_USE_UNLIMITED_PHASES
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(8)
+	#define SGX_FEATURE_NUM_USE_PIPES						(4)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MONOLITHIC_UKERNEL
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+	#define SGX_FEATURE_DATA_BREAKPOINTS
+    #define SGX_FEATURE_PERPIPE_BKPT_REGS
+    #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES          (2)
+	#define SGX_FEATURE_2D_HARDWARE
+	#define SGX_FEATURE_PTLA
+	#define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+	#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+	#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
+		#if defined(SGX_FEATURE_MP)
+		#define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
+		#endif
+		#define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+	#endif
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(4)
+#else
+#if defined(SGX544)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX544"
+	#define SGX_CORE_ID										SGX_CORE_ID_544
+	#define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+	#define SGX_FEATURE_USE_UNLIMITED_PHASES
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(8)
+	#define SGX_FEATURE_NUM_USE_PIPES						(4)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MONOLITHIC_UKERNEL
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+//	#define SGX_FEATURE_DATA_BREAKPOINTS
+//    #define SGX_FEATURE_PERPIPE_BKPT_REGS
+//    #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES          (2)
+	#if defined(SGX_FEATURE_MP)
+		#define SGX_FEATURE_2D_HARDWARE
+		#define SGX_FEATURE_PTLA
+	#endif
+	#define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+	#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+	#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
+		#if defined(SGX_FEATURE_MP)
+		#define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
+		#define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+		#endif
+	#endif
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(4)
+#else
+#if defined(SGX545)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX545"
+	#define SGX_CORE_ID										SGX_CORE_ID_545
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+	#define SGX_FEATURE_USE_UNLIMITED_PHASES
+	#define SGX_FEATURE_VOLUME_TEXTURES
+	#define SGX_FEATURE_HOST_ALLOC_FROM_DPM
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS				(16)
+	#define SGX_FEATURE_NUM_USE_PIPES					(4)
+	#define	SGX_FEATURE_TEXTURESTRIDE_EXTENSION
+	#define SGX_FEATURE_PDS_DATA_INTERLEAVE_2DWORDS
+	#define SGX_FEATURE_MONOLITHIC_UKERNEL
+	#define SGX_FEATURE_ZLS_EXTERNALZ
+	#define SGX_FEATURE_NUM_PDS_PIPES					(2)
+	#define SGX_FEATURE_NATIVE_BACKWARD_BLIT
+	#define SGX_FEATURE_MAX_TA_RENDER_TARGETS				(512)
+	#define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
+	#define SGX_FEATURE_WRITEBACK_DCU
+	//FIXME: this is defined in the build config for now
+	//#define SGX_FEATURE_36BIT_MMU
+	#define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+	#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(4)
+#else
+#if defined(SGX554)
+	#define SGX_CORE_FRIENDLY_NAME							"SGX554"
+	#define SGX_CORE_ID										SGX_CORE_ID_554
+	#define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+	#define SGX_FEATURE_USE_UNLIMITED_PHASES
+	#define SGX_FEATURE_ADDRESS_SPACE_SIZE					(32)
+	#define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+	#define SGX_FEATURE_BIF_NUM_DIRLISTS					(8)
+	#define SGX_FEATURE_NUM_USE_PIPES						(8)
+	#define SGX_FEATURE_AUTOCLOCKGATING
+	#define SGX_FEATURE_MONOLITHIC_UKERNEL
+	#define SGX_FEATURE_MULTI_EVENT_KICK
+//	#define SGX_FEATURE_DATA_BREAKPOINTS
+//    #define SGX_FEATURE_PERPIPE_BKPT_REGS
+//    #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES          (2)
+	#define SGX_FEATURE_2D_HARDWARE
+	#define SGX_FEATURE_PTLA
+	#define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+	#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
+	#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
+		#if defined(SGX_FEATURE_MP)
+		#define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
+		#endif
+		#define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+	#endif
+	#define SGX_FEATURE_PT_CACHE_ENTRIES_PER_LINE			(4)
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH) \
+	|| defined(SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH)
+/* Enable the define so common code for HW VDMCS code is compiled */
+#define SGX_FEATURE_VDM_CONTEXT_SWITCH
+#endif
+
+/*
+	'switch-off' features if defined BRNs affect the feature
+*/
+
+#if defined(FIX_HW_BRN_27266)
+#undef SGX_FEATURE_36BIT_MMU
+#endif
+
+#if defined(FIX_HW_BRN_22934)	\
+	|| defined(FIX_HW_BRN_25499)
+#undef SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+	#if defined(SGX_FEATURE_36BIT_MMU)
+		#error SGX_FEATURE_SYSTEM_CACHE is incompatible with SGX_FEATURE_36BIT_MMU
+	#endif
+	#if defined(FIX_HW_BRN_26620) && !defined(SGX_FEATURE_MULTI_EVENT_KICK)
+		#define SGX_BYPASS_SYSTEM_CACHE
+	#endif
+#endif
+
+#if defined(FIX_HW_BRN_29954)
+#undef SGX_FEATURE_PERPIPE_BKPT_REGS
+#endif
+
+#if defined(FIX_HW_BRN_31620)
+#undef SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+#undef SGX_FEATURE_BIF_NUM_DIRLISTS
+#endif
+
+/*
+	Derive other definitions:
+*/
+
+/* define default MP core count */
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX_FEATURE_MP_CORE_COUNT_TA) && defined(SGX_FEATURE_MP_CORE_COUNT_3D)
+#if (SGX_FEATURE_MP_CORE_COUNT_TA > SGX_FEATURE_MP_CORE_COUNT_3D)
+#error Number of TA cores larger than number of 3D cores not supported in current driver
+#endif /* (SGX_FEATURE_MP_CORE_COUNT_TA > SGX_FEATURE_MP_CORE_COUNT_3D) */
+#else
+#if defined(SGX_FEATURE_MP_CORE_COUNT)
+#define SGX_FEATURE_MP_CORE_COUNT_TA		(SGX_FEATURE_MP_CORE_COUNT)
+#define SGX_FEATURE_MP_CORE_COUNT_3D		(SGX_FEATURE_MP_CORE_COUNT)
+#else
+#error Either SGX_FEATURE_MP_CORE_COUNT or \
+both SGX_FEATURE_MP_CORE_COUNT_TA and SGX_FEATURE_MP_CORE_COUNT_3D \
+must be defined when SGX_FEATURE_MP is defined
+#endif /* SGX_FEATURE_MP_CORE_COUNT */
+#endif /* defined(SGX_FEATURE_MP_CORE_COUNT_TA) && defined(SGX_FEATURE_MP_CORE_COUNT_3D) */
+#else
+#define SGX_FEATURE_MP_CORE_COUNT		(1)
+#define SGX_FEATURE_MP_CORE_COUNT_TA	(1)
+#define SGX_FEATURE_MP_CORE_COUNT_3D	(1)
+#endif /* SGX_FEATURE_MP */
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING
+#endif
+
+#include "img_types.h"
+
+/******************************************************************************
+ End of file (sgxfeaturedefs.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxmmu.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxmmu.h
new file mode 100644
index 0000000..a6a907a
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxmmu.h
@@ -0,0 +1,99 @@
+/*************************************************************************/ /*!
+@Title          SGX MMU defines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provides SGX MMU declarations and macros
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+/* to be implemented */
+
+/* SGX MMU maps 4Kb pages */
+#define SGX_MMU_PAGE_SHIFT				(12)
+#define SGX_MMU_PAGE_SIZE				(1U<<SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK				(SGX_MMU_PAGE_SIZE - 1U)
+
+/* PD details */
+#define SGX_MMU_PD_SHIFT				(10)
+#define SGX_MMU_PD_SIZE					(1U<<SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK					(0xFFC00000U)
+
+/* PD Entry details */
+#if defined(SGX_FEATURE_36BIT_MMU)
+	#define SGX_MMU_PDE_ADDR_MASK			(0xFFFFFF00U)
+	#define SGX_MMU_PDE_ADDR_ALIGNSHIFT		(4)
+#else
+	#define SGX_MMU_PDE_ADDR_MASK			(0xFFFFF000U)
+	#define SGX_MMU_PDE_ADDR_ALIGNSHIFT		(0)
+#endif
+#define SGX_MMU_PDE_VALID				(0x00000001U)
+/* variable page size control field */
+#define SGX_MMU_PDE_PAGE_SIZE_4K		(0x00000000U)
+#define SGX_MMU_PDE_PAGE_SIZE_16K		(0x00000002U)
+#define SGX_MMU_PDE_PAGE_SIZE_64K		(0x00000004U)
+#define SGX_MMU_PDE_PAGE_SIZE_256K		(0x00000006U)
+#define SGX_MMU_PDE_PAGE_SIZE_1M		(0x00000008U)
+#define SGX_MMU_PDE_PAGE_SIZE_4M		(0x0000000AU)
+#define SGX_MMU_PDE_PAGE_SIZE_MASK		(0x0000000EU)
+
+/* PT details */
+#define SGX_MMU_PT_SHIFT				(10)
+#define SGX_MMU_PT_SIZE					(1U<<SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK					(0x003FF000U)
+
+/* PT Entry details */
+#if defined(SGX_FEATURE_36BIT_MMU)
+	#define SGX_MMU_PTE_ADDR_MASK			(0xFFFFFF00U)
+	#define SGX_MMU_PTE_ADDR_ALIGNSHIFT		(4)
+#else
+	#define SGX_MMU_PTE_ADDR_MASK			(0xFFFFF000U)
+	#define SGX_MMU_PTE_ADDR_ALIGNSHIFT		(0)
+#endif
+#define SGX_MMU_PTE_VALID				(0x00000001U)
+#define SGX_MMU_PTE_WRITEONLY			(0x00000002U)
+#define SGX_MMU_PTE_READONLY			(0x00000004U)
+#define SGX_MMU_PTE_CACHECONSISTENT		(0x00000008U)
+#define SGX_MMU_PTE_EDMPROTECT			(0x00000010U)
+
+#endif	/* __SGXMMU_KM_H__ */
+
+/*****************************************************************************
+ End of file (sgxmmu.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxmpdefs.h b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxmpdefs.h
new file mode 100644
index 0000000..a4cd81e
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/hwdefs/sgxmpdefs.h
@@ -0,0 +1,387 @@
+/*************************************************************************/ /*!
+@Title          Hardware defs for SGXMP.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SGXMPDEFS_KM_H_
+#define _SGXMPDEFS_KM_H_
+
+/* Register EUR_CR_MASTER_BIF_CTRL */
+#define EUR_CR_MASTER_BIF_CTRL              0x4C00
+#define EUR_CR_MASTER_BIF_CTRL_NOREORDER_MASK 0x00000001U
+#define EUR_CR_MASTER_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_MASTER_BIF_CTRL_NOREORDER_SIGNED 0
+#define EUR_CR_MASTER_BIF_CTRL_PAUSE_MASK   0x00000002U
+#define EUR_CR_MASTER_BIF_CTRL_PAUSE_SHIFT  1
+#define EUR_CR_MASTER_BIF_CTRL_PAUSE_SIGNED 0
+#define EUR_CR_MASTER_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010U
+#define EUR_CR_MASTER_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_MASTER_BIF_CTRL_CLEAR_FAULT_SIGNED 0
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_PTLA_MASK 0x00010000U
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_PTLA_SHIFT 16
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_PTLA_SIGNED 0
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_VDM_MASK 0x00020000U
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SHIFT 17
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_VDM_SIGNED 0
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_IPF_MASK 0x00040000U
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SHIFT 18
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_IPF_SIGNED 0
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
+#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_INT_STAT */
+#define EUR_CR_MASTER_BIF_INT_STAT          0x4C04
+#define EUR_CR_MASTER_BIF_INT_STAT_FAULT_REQ_MASK 0x00003FFFU
+#define EUR_CR_MASTER_BIF_INT_STAT_FAULT_REQ_SHIFT 0
+#define EUR_CR_MASTER_BIF_INT_STAT_FAULT_REQ_SIGNED 0
+#define EUR_CR_MASTER_BIF_INT_STAT_FAULT_TYPE_MASK 0x00070000U
+#define EUR_CR_MASTER_BIF_INT_STAT_FAULT_TYPE_SHIFT 16
+#define EUR_CR_MASTER_BIF_INT_STAT_FAULT_TYPE_SIGNED 0
+#define EUR_CR_MASTER_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000U
+#define EUR_CR_MASTER_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
+#define EUR_CR_MASTER_BIF_INT_STAT_FLUSH_COMPLETE_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_FAULT */
+#define EUR_CR_MASTER_BIF_FAULT             0x4C08
+#define EUR_CR_MASTER_BIF_FAULT_CID_MASK    0x0000000FU
+#define EUR_CR_MASTER_BIF_FAULT_CID_SHIFT   0
+#define EUR_CR_MASTER_BIF_FAULT_CID_SIGNED  0
+#define EUR_CR_MASTER_BIF_FAULT_SB_MASK     0x000001F0U
+#define EUR_CR_MASTER_BIF_FAULT_SB_SHIFT    4
+#define EUR_CR_MASTER_BIF_FAULT_SB_SIGNED   0
+#define EUR_CR_MASTER_BIF_FAULT_ADDR_MASK   0xFFFFF000U
+#define EUR_CR_MASTER_BIF_FAULT_ADDR_SHIFT  12
+#define EUR_CR_MASTER_BIF_FAULT_ADDR_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_CTRL_INVAL */
+#define EUR_CR_MASTER_BIF_CTRL_INVAL        0x4C34
+#define EUR_CR_MASTER_BIF_CTRL_INVAL_PTE_MASK 0x00000004U
+#define EUR_CR_MASTER_BIF_CTRL_INVAL_PTE_SHIFT 2
+#define EUR_CR_MASTER_BIF_CTRL_INVAL_PTE_SIGNED 0
+#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_MASK 0x00000008U
+#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_SHIFT 3
+#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_MMU_CTRL */
+#define EUR_CR_MASTER_BIF_MMU_CTRL          0x4CD0
+#define EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
+#define EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
+#define EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_SIGNED 0
+#define EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_MASK 0x00000006U
+#define EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT 1
+#define EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SIGNED 0
+#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK 0x00000010U
+#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_SHIFT 4
+#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL */
+#define EUR_CR_MASTER_SLC_CTRL              0x4D00
+#define EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK 0x00800000U
+#define EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_SHIFT 23
+#define EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_DISABLE_BURST_EXP_MASK 0x00400000U
+#define EUR_CR_MASTER_SLC_CTRL_DISABLE_BURST_EXP_SHIFT 22
+#define EUR_CR_MASTER_SLC_CTRL_DISABLE_BURST_EXP_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ3_MASK 0x00200000U
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ3_SHIFT 21
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ3_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ2_MASK 0x00100000U
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ2_SHIFT 20
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ2_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ1_MASK 0x00080000U
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ1_SHIFT 19
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ1_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK 0x00040000U
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_SHIFT 18
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_DM_REF_SET_ALL_MASK 0x00010000U
+#define EUR_CR_MASTER_SLC_CTRL_DM_REF_SET_ALL_SHIFT 16
+#define EUR_CR_MASTER_SLC_CTRL_DM_REF_SET_ALL_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_MASK 0x0000F000U
+#define EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT 12
+#define EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_MASK 0x00000E00U
+#define EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT 9
+#define EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_PAUSE_MASK   0x00000100U
+#define EUR_CR_MASTER_SLC_CTRL_PAUSE_SHIFT  8
+#define EUR_CR_MASTER_SLC_CTRL_PAUSE_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_BYPASS */
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS       0x4D04
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_N_MASK 0x08000000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_N_SHIFT 27
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_N_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK 0x04000000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_SHIFT 26
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE4_MASK 0x02000000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE4_SHIFT 25
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE4_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE3_MASK 0x01000000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE3_SHIFT 24
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE3_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE2_MASK 0x00800000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE2_SHIFT 23
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE2_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE1_MASK 0x00400000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE1_SHIFT 22
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE1_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE0_MASK 0x00200000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE0_SHIFT 21
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_CORE0_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PTLA_MASK 0x00100000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PTLA_SHIFT 20
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PTLA_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_ISP2_RCIF_MASK 0x00080000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_ISP2_RCIF_SHIFT 19
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_ISP2_RCIF_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_ZLS_MASK 0x00040000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_ZLS_SHIFT 18
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_ZLS_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PBE_MASK 0x00020000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PBE_SHIFT 17
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PBE_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_VDM_MASK 0x00010000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_VDM_SHIFT 16
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_VDM_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_IPF_MASK 0x00008000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_IPF_SHIFT 15
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_IPF_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PDS_MASK 0x00004000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PDS_SHIFT 14
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_PDS_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USEC_MASK 0x00002000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USEC_SHIFT 13
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USEC_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK 0x00001000U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_SHIFT 12
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_MASK 0x00000800U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_SHIFT 11
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_MASK 0x00000400U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_SHIFT 10
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_MASK 0x00000200U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_SHIFT 9
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_IPF_OBJ_MASK 0x00000100U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_IPF_OBJ_SHIFT 8
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_IPF_OBJ_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TPF_MASK 0x00000080U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TPF_SHIFT 7
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TPF_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK 0x00000040U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_SHIFT 6
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_CACHE_MASK 0x00000020U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_CACHE_SHIFT 5
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_CACHE_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_MMU_MASK 0x00000010U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_MMU_SHIFT 4
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_MMU_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_EVENT_MASK 0x00000008U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_EVENT_SHIFT 3
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_EVENT_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_PIXEL_MASK 0x00000004U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_PIXEL_SHIFT 2
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_PIXEL_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_VERTEX_MASK 0x00000002U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_VERTEX_SHIFT 1
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_DM_VERTEX_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_MASK 0x00000001U
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_SHIFT 0
+#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_USSE_INVAL */
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL   0x4D08
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_MASK 0xFFFFFFFFU
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_SHIFT 0
+#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_INVAL */
+#define EUR_CR_MASTER_SLC_CTRL_INVAL        0x4D28
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_EVENT_MASK 0x00000008U
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_EVENT_SHIFT 3
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_EVENT_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_PIXEL_MASK 0x00000004U
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_PIXEL_SHIFT 2
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_PIXEL_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_VERTEX_MASK 0x00000002U
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_VERTEX_SHIFT 1
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_VERTEX_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_MASK 0x00000001U
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_SHIFT 0
+#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_FLUSH */
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH        0x4D2C
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_EVENT_MASK 0x00000080U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_EVENT_SHIFT 7
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_EVENT_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_PIXEL_MASK 0x00000040U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_PIXEL_SHIFT 6
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_PIXEL_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_VERTEX_MASK 0x00000020U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_VERTEX_SHIFT 5
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_VERTEX_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_MASK 0x00000010U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_SHIFT 4
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_FLUSH_INV */
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV    0x4D34
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_EVENT_MASK 0x00000080U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_EVENT_SHIFT 7
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_EVENT_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_PIXEL_MASK 0x00000040U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_PIXEL_SHIFT 6
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_PIXEL_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_VERTEX_MASK 0x00000020U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_VERTEX_SHIFT 5
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_VERTEX_SIGNED 0
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_MASK 0x00000010U
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_SHIFT 4
+#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_READ */
+#define EUR_CR_MASTER_BREAKPOINT_READ       0x4F18
+#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_SHIFT 4
+#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP */
+#define EUR_CR_MASTER_BREAKPOINT_TRAP       0x4F1C
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_SIGNED 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT */
+#define EUR_CR_MASTER_BREAKPOINT            0x4F20
+#define EUR_CR_MASTER_BREAKPOINT_ID_MASK    0x00000030U
+#define EUR_CR_MASTER_BREAKPOINT_ID_SHIFT   4
+#define EUR_CR_MASTER_BREAKPOINT_ID_SIGNED  0
+#define EUR_CR_MASTER_BREAKPOINT_UNTRAPPED_MASK 0x00000008U
+#define EUR_CR_MASTER_BREAKPOINT_UNTRAPPED_SHIFT 3
+#define EUR_CR_MASTER_BREAKPOINT_UNTRAPPED_SIGNED 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK 0x00000004U
+#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_SHIFT 2
+#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0 */
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0 0x4F24
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1 */
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1 0x4F28
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_SIZE_SIGNED 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_NUMBER_MASK 0x00000300U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT 8
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_NUMBER_SIGNED 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_TAG_MASK 0x000000F8U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_TAG_SHIFT 3
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_TAG_SIGNED 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK 0x00000006U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT 1
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SIGNED 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
+#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_MASTER_CORE */
+#define EUR_CR_MASTER_CORE                  0x4000
+#define EUR_CR_MASTER_CORE_ENABLE_MASK      0x00000003U
+#define EUR_CR_MASTER_CORE_ENABLE_SHIFT     0
+#define EUR_CR_MASTER_CORE_ENABLE_SIGNED    0
+/* Register EUR_CR_MASTER_CORE_ID */
+#define EUR_CR_MASTER_CORE_ID               0x4010
+#define EUR_CR_MASTER_CORE_ID_CONFIG_MULTI_MASK 0x00000001U
+#define EUR_CR_MASTER_CORE_ID_CONFIG_MULTI_SHIFT 0
+#define EUR_CR_MASTER_CORE_ID_CONFIG_MULTI_SIGNED 0
+#define EUR_CR_MASTER_CORE_ID_CONFIG_BASE_MASK 0x00000002U
+#define EUR_CR_MASTER_CORE_ID_CONFIG_BASE_SHIFT 1
+#define EUR_CR_MASTER_CORE_ID_CONFIG_BASE_SIGNED 0
+#define EUR_CR_MASTER_CORE_ID_CONFIG_MASK   0x000000FCU
+#define EUR_CR_MASTER_CORE_ID_CONFIG_SHIFT  2
+#define EUR_CR_MASTER_CORE_ID_CONFIG_SIGNED 0
+#define EUR_CR_MASTER_CORE_ID_CONFIG_CORES_MASK 0x00000F00U
+#define EUR_CR_MASTER_CORE_ID_CONFIG_CORES_SHIFT 8
+#define EUR_CR_MASTER_CORE_ID_CONFIG_CORES_SIGNED 0
+#define EUR_CR_MASTER_CORE_ID_CONFIG_SLC_MASK 0x0000F000U
+#define EUR_CR_MASTER_CORE_ID_CONFIG_SLC_SHIFT 12
+#define EUR_CR_MASTER_CORE_ID_CONFIG_SLC_SIGNED 0
+#define EUR_CR_MASTER_CORE_ID_ID_MASK       0xFFFF0000U
+#define EUR_CR_MASTER_CORE_ID_ID_SHIFT      16
+#define EUR_CR_MASTER_CORE_ID_ID_SIGNED     0
+/* Register EUR_CR_MASTER_CORE_REVISION */
+#define EUR_CR_MASTER_CORE_REVISION         0x4014
+#define EUR_CR_MASTER_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_MASTER_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_MASTER_CORE_REVISION_MAINTENANCE_SIGNED 0
+#define EUR_CR_MASTER_CORE_REVISION_MINOR_MASK 0x0000FF00U
+#define EUR_CR_MASTER_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_MASTER_CORE_REVISION_MINOR_SIGNED 0
+#define EUR_CR_MASTER_CORE_REVISION_MAJOR_MASK 0x00FF0000U
+#define EUR_CR_MASTER_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_MASTER_CORE_REVISION_MAJOR_SIGNED 0
+#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_MASK 0xFF000000U
+#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_MASTER_SOFT_RESET */
+#define EUR_CR_MASTER_SOFT_RESET            0x4080
+#define EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(i) (0x00000001U << (0 + ((i) * 1)))
+#define EUR_CR_MASTER_SOFT_RESET_CORE_RESET_SHIFT(i) (0 + ((i) * 1))
+#define EUR_CR_MASTER_SOFT_RESET_CORE_RESET_REGNUM(i) 0x4080
+#define EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK 0x00000010U
+#define EUR_CR_MASTER_SOFT_RESET_IPF_RESET_SHIFT 4
+#define EUR_CR_MASTER_SOFT_RESET_IPF_RESET_SIGNED 0
+#define EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK 0x00000020U
+#define EUR_CR_MASTER_SOFT_RESET_DPM_RESET_SHIFT 5
+#define EUR_CR_MASTER_SOFT_RESET_DPM_RESET_SIGNED 0
+#define EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK 0x00000040U
+#define EUR_CR_MASTER_SOFT_RESET_VDM_RESET_SHIFT 6
+#define EUR_CR_MASTER_SOFT_RESET_VDM_RESET_SIGNED 0
+#define EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK 0x00000080U
+#define EUR_CR_MASTER_SOFT_RESET_SLC_RESET_SHIFT 7
+#define EUR_CR_MASTER_SOFT_RESET_SLC_RESET_SIGNED 0
+#define EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK 0x00000100U
+#define EUR_CR_MASTER_SOFT_RESET_BIF_RESET_SHIFT 8
+#define EUR_CR_MASTER_SOFT_RESET_BIF_RESET_SIGNED 0
+#define EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK 0x00000200U
+#define EUR_CR_MASTER_SOFT_RESET_MCI_RESET_SHIFT 9
+#define EUR_CR_MASTER_SOFT_RESET_MCI_RESET_SIGNED 0
+#define EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK 0x00000400U
+#define EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_SHIFT 10
+#define EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_SIGNED 0
+
+#endif /* _SGXMPDEFS_KM_H_ */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/include/buffer_manager.h b/drivers/gpu/pvr/services4/srvkm/include/buffer_manager.h
new file mode 100644
index 0000000..a23529a
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/buffer_manager.h
@@ -0,0 +1,640 @@
+/*************************************************************************/ /*!
+@Title          Buffer Management.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Manages buffers mapped into two virtual memory spaces, host and
+                device and referenced by handles.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _BUFFER_MANAGER_H_
+#define _BUFFER_MANAGER_H_
+
+#include "img_types.h"
+#include "ra.h"
+#include "perproc.h"
+
+#if defined(__cplusplus)
+extern "C"{
+#endif
+
+/* forward reference */
+typedef struct _BM_HEAP_ BM_HEAP;
+
+/*
+ * The mapping structure is used to record relations between CPU virtual,
+ * CPU physical and device virtual addresses for large chunks of memory
+ * from which we have resource-allocator draw our buffers.
+ *
+ * There is one per contiguous pool and one per import from the host OS.
+ */
+struct _BM_MAPPING_
+{
+	enum
+	{
+		hm_wrapped = 1,		/*!< wrapped user supplied contiguous*/
+		hm_wrapped_scatter,	/*!< wrapped user supplied scattered */
+		hm_wrapped_virtaddr, /*!< wrapped user supplied contiguous with virtual address*/
+		hm_wrapped_scatter_virtaddr, /*!< wrapped user supplied scattered with virtual address*/
+		hm_env,				/*!< obtained from environment */
+		hm_contiguous		/*!< contiguous arena */
+	} eCpuMemoryOrigin;
+
+	BM_HEAP				*pBMHeap;	/* which BM heap */
+	RA_ARENA			*pArena;	/* whence the memory comes */
+
+	IMG_CPU_VIRTADDR	CpuVAddr;
+	IMG_CPU_PHYADDR		CpuPAddr;
+	IMG_DEV_VIRTADDR	DevVAddr;
+	IMG_SYS_PHYADDR		*psSysAddr;
+	IMG_SIZE_T			uSize;
+	IMG_SIZE_T			uSizeVM;
+	IMG_HANDLE			hOSMemHandle;
+	IMG_UINT32			ui32Flags;
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+	IMG_UINT32			ui32TimeToDevMap;	/* Time taken (in microseconds) to map this memory in device MMU */
+	IMG_UINT32			*pui32TimeToDevUnmap; /* Time taken (in microseconds) to unmap this memory from Device MMU.
+													NOTE - API user provided address to store this info, if at all  */
+#endif
+
+	/* Sparse mapping data */
+	IMG_UINT32			ui32ChunkSize;
+	IMG_UINT32			ui32NumVirtChunks;
+	IMG_UINT32			ui32NumPhysChunks;
+	IMG_BOOL			*pabMapChunk;
+};
+
+/*
+ * The buffer structure handles individual allocations from the user; thus
+ * there is one allocated per call to BM_Alloc and one per call to BM_Wrap.
+ * We record a mapping reference so we know where to return allocated
+ * resources at BM_Free time.
+ */
+typedef struct _BM_BUF_
+{
+	IMG_CPU_VIRTADDR	*CpuVAddr;
+	IMG_VOID			*hOSMemHandle;
+	IMG_CPU_PHYADDR		CpuPAddr;
+	IMG_DEV_VIRTADDR	DevVAddr;
+
+	BM_MAPPING			*pMapping;
+	IMG_UINT32			ui32RefCount;
+	IMG_UINT32			ui32ExportCount;
+} BM_BUF;
+
+struct _BM_HEAP_
+{
+	IMG_UINT32				ui32Attribs;
+	BM_CONTEXT				*pBMContext;
+	RA_ARENA				*pImportArena;
+	RA_ARENA				*pLocalDevMemArena;
+	RA_ARENA				*pVMArena;
+	DEV_ARENA_DESCRIPTOR	sDevArena;
+	MMU_HEAP				*pMMUHeap;
+	PDUMP_MMU_ATTRIB 		*psMMUAttrib;
+	
+	struct _BM_HEAP_ 		*psNext;
+	struct _BM_HEAP_ 		**ppsThis;
+	/* BIF tile stride for this heap */
+	IMG_UINT32 				ui32XTileStride;
+};
+
+/*
+ * The bm-context structure
+ */
+struct _BM_CONTEXT_
+{
+	MMU_CONTEXT	*psMMUContext;
+
+	/*
+	 * Resource allocation arena of dual mapped pages. For devices
+	 * where the hardware imposes different constraints on the valid
+	 * device virtual address range depending on the use of the buffer
+	 * we maintain two allocation arenas, one low address range, the
+	 * other high. For devices without such a constrain we do not
+	 * create the high arena, instead all allocations come from the
+	 * low arena.
+	 */
+	 BM_HEAP *psBMHeap;
+
+	/*
+	 * The Shared Heaps
+	 */
+	 BM_HEAP *psBMSharedHeap;
+
+	PVRSRV_DEVICE_NODE *psDeviceNode;
+
+	/*
+	 * Hash table management.
+	 */
+	HASH_TABLE *pBufferHash;
+
+	/*
+	 *	Resman item handle
+	 */
+	IMG_HANDLE hResItem;
+
+	IMG_UINT32 ui32RefCount;
+
+	/*
+		linked list next pointer
+	*/
+	struct _BM_CONTEXT_ *psNext;
+	struct _BM_CONTEXT_ **ppsThis;
+};
+
+/* refcount.c needs to know the internals of this structure */
+typedef struct _XPROC_DATA_{
+	IMG_UINT32 ui32RefCount;
+	IMG_UINT32 ui32AllocFlags;
+	IMG_UINT32 ui32Size;
+	IMG_UINT32 ui32PageSize;
+	RA_ARENA *psArena;
+	IMG_SYS_PHYADDR sSysPAddr;
+	IMG_VOID *pvCpuVAddr;
+	IMG_HANDLE hOSMemHandle;
+} XPROC_DATA;
+
+extern XPROC_DATA gXProcWorkaroundShareData[];
+/*
+	Buffer handle.
+*/
+typedef IMG_VOID *BM_HANDLE;
+
+/** Buffer manager allocation flags.
+ *
+ *  Flags passed to BM_Alloc to specify buffer capabilities.
+ *
+ * @defgroup BP Buffer Manager Allocation Flags
+ * @{
+ */
+
+/** Pool number mask. */
+#define BP_POOL_MASK         0x7
+
+/* Request physically contiguous pages of memory */
+#define BP_CONTIGUOUS			(1 << 3)
+#define BP_PARAMBUFFER			(1 << 4)
+
+#define BM_MAX_DEVMEM_ARENAS  2
+
+/** @} */
+
+/**
+ *  @Function BM_CreateContext
+ *
+ *  @Description
+ *
+ *  @Input
+
+ *  @Return
+ */
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE			*psDeviceNode,
+				 IMG_DEV_PHYADDR			*psPDDevPAddr,
+				 PVRSRV_PER_PROCESS_DATA	*psPerProc,
+				 IMG_BOOL					*pbCreated);
+
+
+/**
+ *  @Function   BM_DestroyContext
+ *
+ *  @Description
+ *
+ *  @Input
+ *
+ *  @Return PVRSRV_ERROR
+ */
+PVRSRV_ERROR
+BM_DestroyContext (IMG_HANDLE hBMContext,
+					IMG_BOOL *pbCreated);
+
+
+/**
+ *  @Function   BM_CreateHeap
+ *
+ *  @Description
+ *
+ *  @Input
+ *
+ *  @Return
+ */
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+				DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+
+/**
+ *  @Function   BM_DestroyHeap
+ *
+ *  @Description
+ *
+ *  @Input
+ *
+ *  @Return
+ */
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+
+
+/**
+ *  @Function   BM_Reinitialise
+ *
+ *  @Description
+ *
+ *  Reinitialises the buffer manager after a power event. Calling this
+ *  function will reprogram MMU registers and re-enable the MMU.
+ *
+ *  @Input None
+ *  @Return None
+ */
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/**
+ *  @Function   BM_Alloc
+ *
+ *  @Description
+ *
+ *  Allocate a buffer mapped into both host and device virtual memory
+ *  maps.
+ *
+ *  @Input uSize - require size in bytes of the buffer.
+ *  @Input/Output pui32Flags - bit mask of buffer property flags + receives heap flags.
+ *  @Input uDevVAddrAlignment - required alignment in bytes, or 0.
+ *  @Input pvPrivData - private data passed to OS allocator
+ *  @Input ui32PrivDataLength - length of private data
+ *  @Input ui32ChunkSize - Chunk size
+ *  @Input ui32NumVirtChunks - Number of virtual chunks
+ *  @Input ui32NumPhysChunks - Number of physical chunks
+ *  @Input pabMapChunk - Chunk mapping array
+ *  @Output pui32TimeToDevMap - Available only when PVRSRV_DEVMEM_TIME_STATS defined,
+ *                              contains time taken (in microseconds) to map this buffer
+ *                              to Device MMU.
+ *  @Output phBuf - receives the buffer handle.
+ *  @Return IMG_TRUE - Success, IMG_FALSE - Failed.
+ */
+IMG_BOOL
+BM_Alloc (IMG_HANDLE			hDevMemHeap,
+			IMG_DEV_VIRTADDR	*psDevVAddr,
+			IMG_SIZE_T			uSize,
+			IMG_UINT32			*pui32Flags,
+			IMG_UINT32			uDevVAddrAlignment,
+			IMG_PVOID			pvPrivData,
+			IMG_UINT32			ui32PrivDataLength,
+			IMG_UINT32			ui32ChunkSize,
+			IMG_UINT32			ui32NumVirtChunks,
+			IMG_UINT32			ui32NumPhysChunks,
+			IMG_BOOL			*pabMapChunk,
+			#if defined (PVRSRV_DEVMEM_TIME_STATS)
+			IMG_UINT32			*pui32TimeToDevMap,
+			#endif
+			BM_HANDLE			*phBuf);
+
+/**
+ *  @Function   BM_Wrap
+ *
+ *  @Description
+ *
+ *  Create a buffer which wraps user provided host physical memory.
+ *  The wrapped memory must be page aligned. BM_Wrap will roundup the
+ *  size to a multiple of host pages.
+ *
+ *  @Input ui32Size - size of memory to wrap.
+ *  @Input ui32Offset - Offset into page of memory to wrap.
+ *  @Input bPhysContig - Is the wrap physically contiguous.
+ *  @Input psSysAddr - list of system physical page addresses of memory to wrap.
+ *	@Input pvCPUVAddr - optional CPU kernel virtual address (Page aligned) of memory to wrap.
+ *  @Input uFlags - bit mask of buffer property flags.
+ *  @Input phBuf - receives the buffer handle.
+ *  @Return IMG_TRUE - Success, IMG_FALSE - Failed
+ */
+IMG_BOOL
+BM_Wrap (	IMG_HANDLE hDevMemHeap,
+			IMG_SIZE_T uSize,
+			IMG_SIZE_T uOffset,
+			IMG_BOOL bPhysContig,
+			IMG_SYS_PHYADDR *psSysAddr,
+			IMG_VOID *pvCPUVAddr,
+			IMG_UINT32 *pui32Flags,
+			BM_HANDLE *phBuf);
+
+/**
+ *  @Function   BM_Free
+ *
+ *  @Description
+ *
+ *  Free a buffer previously allocated via BM_Alloc.
+ *
+ *  @Input  hBuf - buffer handle.
+ *  @Output pui32TimeToDevUnmap - Time taken in us to "unmap"
+ *		the memory from Device MMU
+ *  @Return None.
+ */
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+		IMG_UINT32 ui32Flags
+		#if defined(PVRSRV_DEVMEM_TIME_STATS)
+		, IMG_UINT32 *pui32TimeToDevUnmap
+		#endif
+		);
+
+
+/**
+ *  @Function   BM_HandleToCpuVaddr
+ *
+ *  @Description
+ *
+ *  Retrieve the host virtual address associated with a buffer.
+ *
+ *  @Input  hBuf - buffer handle.
+ *
+ *  @Return buffers host virtual address.
+ */
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+
+/**
+ *  @Function   BM_HandleToDevVaddr
+ *
+ *  @Description
+ *
+ *  Retrieve the device virtual address associated with a buffer.
+ *
+ *  @Input hBuf - buffer handle.
+ *  @Return buffers device virtual address.
+ */
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf);
+
+/**
+ *  @Function   BM_HandleToSysPaddr
+ *
+ *  @Description
+ *
+ *  Retrieve the system physical address associated with a buffer.
+ *
+ *  @Input hBuf - buffer handle.
+ *  @Return buffers device virtual address.
+ */
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf);
+
+/**
+ *  @Function   BM_HandleToMemOSHandle
+ *
+ *  @Description
+ *
+ *  Retrieve the underlying memory handle associated with a buffer.
+ *
+ *  @Input hBuf - buffer handle.
+ *  @Return An OS Specific memory handle
+ */
+IMG_HANDLE
+BM_HandleToOSMemHandle (BM_HANDLE hBuf);
+
+/**
+ *  @Function   BM_GetPhysPageAddr
+ *
+ *  @Description
+ *
+ *  Retrieve physical address backing dev V address
+ *
+ *  @Input psMemInfo
+ *  @Input sDevVPageAddr
+ *  @Output psDevPAddr
+ *  @Return PVRSRV_ERROR
+ */
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								IMG_DEV_VIRTADDR sDevVPageAddr,
+								IMG_DEV_PHYADDR *psDevPAddr);
+
+/*!
+******************************************************************************
+ @Function	 	BM_GetMMUContext
+
+ @Description
+ 				utility function to return the MMU context
+
+ @inputs        hDevMemHeap - the Dev mem heap handle
+
+ @Return   		MMU context, else NULL
+**************************************************************************/
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+
+/*!
+******************************************************************************
+ @Function	 	BM_GetMMUContextFromMemContext
+
+ @Description
+ 				utility function to return the MMU context
+
+ @inputs        hDevMemHeap - the Dev mem heap handle
+
+ @Return   		MMU context, else NULL
+**************************************************************************/
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+
+/*!
+******************************************************************************
+ @Function	 	BM_GetMMUHeap
+
+ @Description
+ 				utility function to return the MMU heap handle
+
+ @inputs        hDevMemHeap - the Dev mem heap handle
+
+ @Return   		MMU heap handle, else NULL
+**************************************************************************/
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+
+/*!
+******************************************************************************
+ @Function	 	BM_GetDeviceNode
+
+ @Description	utility function to return the devicenode from the BM Context
+
+ @inputs        hDevMemContext - the Dev Mem Context
+
+ @Return   		MMU heap handle, else NULL
+**************************************************************************/
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+
+
+/*!
+******************************************************************************
+ @Function	 	BM_GetMappingHandle
+
+ @Description	utility function to return the mapping handle from a meminfo
+
+ @inputs        psMemInfo - kernel meminfo
+
+ @Return   		mapping handle, else NULL
+**************************************************************************/
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+/*!
+******************************************************************************
+ @Function	 	BM_Export
+
+ @Description	Export a buffer previously allocated via BM_Alloc.
+
+ @inputs        hBuf - buffer handle.
+
+ @Return   		None.
+**************************************************************************/
+IMG_VOID BM_Export(BM_HANDLE hBuf);
+
+/*!
+******************************************************************************
+ @Function	 	BM_FreeExport
+
+ @Description	Free a buffer previously exported via BM_Export.
+
+ @inputs        hBuf - buffer handle.
+                ui32Flags - flags
+
+ @Return   		None.
+**************************************************************************/
+IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
+
+/*!
+******************************************************************************
+ @Function	BM_MappingHandleFromBuffer
+
+ @Description	utility function to get the BM mapping handle from a BM buffer
+
+ @Input     hBuffer - Handle to BM buffer
+
+ @Return	BM mapping handle
+**************************************************************************/
+IMG_HANDLE BM_MappingHandleFromBuffer(IMG_HANDLE hBuffer);
+
+/*!
+******************************************************************************
+ @Function	BM_GetVirtualSize
+
+ @Description	utility function to get the VM size of a BM mapping
+
+ @Input     hBMHandle - Handle to BM mapping
+
+ @Return	VM size of mapping
+**************************************************************************/
+IMG_UINT32 BM_GetVirtualSize(IMG_HANDLE hBMHandle);
+
+/*!
+******************************************************************************
+ @Function	BM_MapPageAtOffset
+
+ @Description	utility function check if the specified offset in a BM mapping
+                is a page that needs to be mapped
+
+ @Input     hBMHandle - Handle to BM mapping
+
+ @Input     ui32Offset - Offset into import
+
+ @Return	IMG_TRUE if the page should be mapped
+**************************************************************************/
+IMG_BOOL BM_MapPageAtOffset(IMG_HANDLE hBMHandle, IMG_UINT32 ui32Offset);
+
+/*!
+******************************************************************************
+ @Function	BM_VirtOffsetToPhysical
+
+ @Description	utility function find of physical offset of a sparse allocation
+                from its virtual offset.
+
+ @Input     hBMHandle - Handle to BM mapping
+
+ @Input     ui32VirtOffset - Virtual offset into allocation
+ 
+ @Output    pui32PhysOffset - Physical offset
+
+ @Return	IMG_TRUE if the virtual offset is physically backed
+**************************************************************************/
+IMG_BOOL BM_VirtOffsetToPhysical(IMG_HANDLE hBMHandle,
+								   IMG_UINT32 ui32VirtOffset,
+								   IMG_UINT32 *pui32PhysOffset);
+
+/* The following are present for the "share mem" workaround for
+   cross-process mapping.  This is only valid for a specific
+   use-case, and only tested on Linux (Android) and only
+   superficially at that.  Do not rely on this API! */
+/* The two "Set" functions set a piece of "global" state in the buffer
+   manager, and "Unset" removes this global state.  Therefore, there
+   is no thread-safety here and it's the caller's responsibility to
+   ensure that a mutex is acquired before using these functions or any
+   device memory allocation functions, including, especially,
+   callbacks from RA. */
+/* Once a "Share Index" is set by this means, any requests from the RA
+   to import a block of physical memory shall cause the physical
+   memory allocation to be refcounted, and shared iff the IDs chosen
+   match */
+/* This API is difficult to use, but saves a lot of plumbing in other
+   APIs.  The next generation of this library should have this functionality 
+   plumbed in properly */
+PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index);
+PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index);
+PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index);
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+
+#define BM_XProcIndexAcquire(x...) \
+	_BM_XProcIndexAcquireDebug(__FILE__, __LINE__, x)
+#define BM_XProcIndexRelease(x...) \
+	_BM_XProcIndexReleaseDebug(__FILE__, __LINE__, x)
+
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index);
+
+
+#define BM_XProcIndexAcquire(x) \
+	_BM_XProcIndexAcquire( x)
+#define BM_XProcIndexRelease(x) \
+	_BM_XProcIndexRelease( x)
+#endif
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/include/device.h b/drivers/gpu/pvr/services4/srvkm/include/device.h
new file mode 100644
index 0000000..6ddee5d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/device.h
@@ -0,0 +1,409 @@
+/*************************************************************************/ /*!
+@Title          Common Device header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device related function templates and defines
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __DEVICE_H__
+#define __DEVICE_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+	
+#include "ra.h"  		/* RA_ARENA */
+#include "resman.h"		/* PRESMAN_ITEM */
+
+/* BM context forward reference */
+typedef struct _BM_CONTEXT_ BM_CONTEXT;
+
+/* pre-defined MMU structure forward references */
+typedef struct _MMU_HEAP_ MMU_HEAP;
+typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+
+/* physical resource types: */
+/* contiguous system memory */
+#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG		(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+/* non-contiguous system memory */
+#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG	(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+/* contiguous local device memory */
+#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG		(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+/* non-contiguous local device memory */
+#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG	(1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+
+/* heap types: */
+typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
+#define DEVICE_MEMORY_HEAP_PERCONTEXT		0
+#define DEVICE_MEMORY_HEAP_KERNEL			1
+#define DEVICE_MEMORY_HEAP_SHARED			2
+#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED	3
+
+#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY	1
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV	2	/* FIXME : Optimal Invalidation is not default */
+
+typedef struct _DEVICE_MEMORY_HEAP_INFO_
+{
+	/* heap identifier */
+	IMG_UINT32				ui32HeapID;
+
+	/* heap identifier string */
+	IMG_CHAR				*pszName;
+
+	/* backing store identifier string */
+	IMG_CHAR				*pszBSName;
+	
+	/* Device virtual address of base of heap */
+	IMG_DEV_VIRTADDR		sDevVAddrBase;
+
+	/* heapsize in bytes */
+	IMG_UINT32				ui32HeapSize;
+
+	/* Flags, includes physical resource (backing store type). Must be available to SOC */
+	IMG_UINT32				ui32Attribs;
+
+	/* Heap type: per device, kernel only, shared, shared_exported */
+	DEVICE_MEMORY_HEAP_TYPE	DevMemHeapType;
+	
+	/* kernel heap handle */
+	IMG_HANDLE				hDevMemHeap;
+	
+	/* ptr to local memory allocator for this heap */
+	RA_ARENA				*psLocalDevMemArena;
+
+	/* MMU data page size (4kb, 16kb, 256kb, 1Mb, 4Mb) */
+	IMG_UINT32				ui32DataPageSize;
+
+	IMG_UINT32				ui32XTileStride;
+
+} DEVICE_MEMORY_HEAP_INFO;
+
+typedef struct _DEVICE_MEMORY_INFO_
+{
+	/* size of address space, as log2 */
+	IMG_UINT32				ui32AddressSpaceSizeLog2;
+
+	/* 
+		flags, includes physical memory resource types available to the system.  
+		Allows for validation at heap creation, define PVRSRV_BACKINGSTORE_XXX 
+	*/
+	IMG_UINT32				ui32Flags;
+
+	/* heap count.  Doesn't include additional heaps from PVRSRVCreateDeviceMemHeap */
+	IMG_UINT32				ui32HeapCount;
+	
+	/* the sync heap id - common code needs to know */
+	IMG_UINT32				ui32SyncHeapID;
+	
+	/* heap for buffer mappings  */
+	IMG_UINT32				ui32MappingHeapID;
+
+	/* heap for ion buffers  */
+	IMG_UINT32				ui32IonHeapID;
+
+	/* device memory heap info about each heap in a device address space */
+	DEVICE_MEMORY_HEAP_INFO	*psDeviceMemoryHeap;
+
+	/* BM kernel context for the device */
+    BM_CONTEXT				*pBMKernelContext;
+
+	/* BM context list for the device*/
+    BM_CONTEXT				*pBMContext;
+
+} DEVICE_MEMORY_INFO;
+
+
+/*!
+ ****************************************************************************
+	Device memory descriptor for a given system
+ ****************************************************************************/
+typedef struct DEV_ARENA_DESCRIPTOR_TAG
+{
+	IMG_UINT32				ui32HeapID;		/*!< memory pool has a unique id for diagnostic purposes */
+
+	IMG_CHAR				*pszName;		/*!< memory pool has a unique string for diagnostic purposes */
+
+	IMG_DEV_VIRTADDR		BaseDevVAddr;	/*!< Device virtual base address of the managed memory pool. */
+
+	IMG_UINT32 				ui32Size;		/*!< Size in bytes of the managed memory pool. */
+
+	DEVICE_MEMORY_HEAP_TYPE	DevMemHeapType;/*!< heap type */
+
+	/* MMU data page size (4kb, 16kb, 256kb, 1Mb, 4Mb) */
+	IMG_UINT32				ui32DataPageSize;
+
+	DEVICE_MEMORY_HEAP_INFO	*psDeviceMemoryHeapInfo;
+
+} DEV_ARENA_DESCRIPTOR;
+
+
+/*
+	PDUMP MMU atttributes
+*/
+typedef struct _PDUMP_MMU_ATTRIB_
+{
+	PVRSRV_DEVICE_IDENTIFIER	sDevId;
+	
+	IMG_CHAR	*pszPDRegRegion;
+	
+	/* data page info */
+	IMG_UINT32 ui32DataPageMask;
+
+	/* page table info */
+	IMG_UINT32 ui32PTEValid;
+	IMG_UINT32 ui32PTSize;
+	IMG_UINT32 ui32PTEAlignShift;
+
+	/* page directory info */
+	IMG_UINT32 ui32PDEMask;
+	IMG_UINT32 ui32PDEAlignShift;
+
+} PDUMP_MMU_ATTRIB;
+
+/* forward reference to _SYS_DATA_ */
+typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
+
+typedef struct _PVRSRV_DEVICE_NODE_
+{
+	PVRSRV_DEVICE_IDENTIFIER	sDevId;
+	IMG_UINT32					ui32RefCount;
+
+	/*
+		callbacks the device must support:
+	*/
+	/* device initialiser */
+	PVRSRV_ERROR			(*pfnInitDevice) (IMG_VOID*);
+	/* device deinitialiser */
+	PVRSRV_ERROR			(*pfnDeInitDevice) (IMG_VOID*);
+
+	/* device post-finalise compatibility check */
+	PVRSRV_ERROR			(*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
+
+	/* device MMU interface */
+	PVRSRV_ERROR			(*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
+	IMG_VOID				(*pfnMMUFinalise)(MMU_CONTEXT*);
+	IMG_VOID				(*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
+	MMU_HEAP*				(*pfnMMUCreate)(MMU_CONTEXT*,DEV_ARENA_DESCRIPTOR*,RA_ARENA**,PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+	IMG_VOID				(*pfnMMUDelete)(MMU_HEAP*);
+	IMG_BOOL				(*pfnMMUAlloc)(MMU_HEAP*pMMU,
+										   IMG_SIZE_T uSize,
+										   IMG_SIZE_T *pActualSize,
+										   IMG_UINT32 uFlags,
+										   IMG_UINT32 uDevVAddrAlignment,
+										   IMG_DEV_VIRTADDR *pDevVAddr);
+	IMG_VOID				(*pfnMMUFree)(MMU_HEAP*,IMG_DEV_VIRTADDR,IMG_UINT32);
+	IMG_VOID 				(*pfnMMUEnable)(MMU_HEAP*);
+	IMG_VOID				(*pfnMMUDisable)(MMU_HEAP*);
+	IMG_VOID				(*pfnMMUMapPages)(MMU_HEAP *pMMU,
+											  IMG_DEV_VIRTADDR devVAddr,
+											  IMG_SYS_PHYADDR SysPAddr,
+											  IMG_SIZE_T uSize,
+											  IMG_UINT32 ui32MemFlags,
+											  IMG_HANDLE hUniqueTag);
+	IMG_VOID				(*pfnMMUMapPagesSparse)(MMU_HEAP *pMMU,
+													IMG_DEV_VIRTADDR devVAddr,
+													IMG_SYS_PHYADDR SysPAddr,
+													IMG_UINT32 ui32ChunkSize,
+													IMG_UINT32 ui32NumVirtChunks,
+													IMG_UINT32 ui32NumPhysChunks,
+													IMG_BOOL *pabMapChunk,
+													IMG_UINT32 ui32MemFlags,
+													IMG_HANDLE hUniqueTag);
+
+	IMG_VOID				(*pfnMMUMapShadow)(MMU_HEAP            *pMMU,
+											   IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+											   IMG_SIZE_T          uSize, 
+											   IMG_CPU_VIRTADDR    CpuVAddr,
+											   IMG_HANDLE          hOSMemHandle,
+											   IMG_DEV_VIRTADDR    *pDevVAddr,
+											   IMG_UINT32 ui32MemFlags,
+											   IMG_HANDLE hUniqueTag);
+	IMG_VOID				(*pfnMMUMapShadowSparse)(MMU_HEAP            *pMMU,
+													 IMG_DEV_VIRTADDR    MapBaseDevVAddr,
+													 IMG_UINT32          ui32ChunkSize,
+													 IMG_UINT32          ui32NumVirtChunks,
+													 IMG_UINT32          ui32NumPhysChunks,
+													 IMG_BOOL            *pabMapChunk,
+													 IMG_CPU_VIRTADDR    CpuVAddr,
+													 IMG_HANDLE          hOSMemHandle,
+													 IMG_DEV_VIRTADDR    *pDevVAddr,
+													 IMG_UINT32          ui32MemFlags,
+													 IMG_HANDLE          hUniqueTag);
+
+	IMG_VOID				(*pfnMMUUnmapPages)(MMU_HEAP *pMMU,
+												IMG_DEV_VIRTADDR dev_vaddr,
+												IMG_UINT32 ui32PageCount,
+												IMG_HANDLE hUniqueTag);
+
+	IMG_VOID				(*pfnMMUMapScatter)(MMU_HEAP *pMMU,
+												IMG_DEV_VIRTADDR DevVAddr,
+												IMG_SYS_PHYADDR *psSysAddr,
+												IMG_SIZE_T uSize,
+												IMG_UINT32 ui32MemFlags,
+												IMG_HANDLE hUniqueTag);
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	IMG_BOOL				(*pfnMMUIsHeapShared)(MMU_HEAP *);
+#endif
+	IMG_DEV_PHYADDR			(*pfnMMUGetPhysPageAddr)(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+	IMG_DEV_PHYADDR			(*pfnMMUGetPDDevPAddr)(MMU_CONTEXT *pMMUContext);
+	IMG_VOID				(*pfnMMUGetCacheFlushRange)(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
+	IMG_VOID				(*pfnMMUGetPDPhysAddr)(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
+
+	/* tiling range control functions */
+	PVRSRV_ERROR			(*pfnAllocMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+														PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+														IMG_UINT32 ui32TilingStride,
+														IMG_UINT32 *pui32RangeIndex);
+	PVRSRV_ERROR			(*pfnFreeMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+														IMG_UINT32 ui32RangeIndex);
+
+	/* LISR handler for device */
+	IMG_BOOL				(*pfnDeviceISR)(IMG_VOID*);
+	/* ISR data */
+	IMG_VOID				*pvISRData;
+	/* System/SOC specific interrupt bit relating to this device */
+	IMG_UINT32 				ui32SOCInterruptBit;
+	/* MISR handler for device */
+	IMG_VOID				(*pfnDeviceMISR)(IMG_VOID*);
+
+	/* Software command complete callback for device */
+	IMG_VOID				(*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+	/* Flag indicating that command complete callback needs to be reprocessed */
+	IMG_BOOL				bReProcessDeviceCommandComplete;
+
+	IMG_VOID				(*pfnCacheInvalidate)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+	/* information about the device's address space and heaps */
+	DEVICE_MEMORY_INFO		sDevMemoryInfo;
+
+	/* private device information */
+	IMG_VOID				*pvDevice;
+	IMG_UINT32				ui32pvDeviceSize; /* required by GetClassDeviceInfo API */
+		
+	/* Resource Manager Context */
+	PRESMAN_CONTEXT			hResManContext;
+	
+	/* pointer back to parent sysdata */
+	PSYS_DATA				psSysData;
+	
+	/* default MMU PT/PD backing store to use for the device */
+	RA_ARENA				*psLocalDevMemArena;
+	
+	IMG_UINT32				ui32Flags;
+	
+	struct _PVRSRV_DEVICE_NODE_	*psNext;
+	struct _PVRSRV_DEVICE_NODE_	**ppsThis;
+	
+#if defined(PDUMP)
+	/* 	device-level callback which is called when pdump.exe starts.
+	 *	Should be implemented in device-specific init code, e.g. sgxinit.c
+	 */
+	PVRSRV_ERROR			(*pfnPDumpInitDevice)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+	/* device-level callback to return pdump ID associated to a memory context */
+	IMG_UINT32				(*pfnMMUGetContextID)(IMG_HANDLE hDevMemContext);
+#endif
+} PVRSRV_DEVICE_NODE;
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+											  PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+											  IMG_UINT32 ui32SOCInterruptBit,
+			 								  IMG_UINT32 *pui32DeviceIndex );
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice(IMG_UINT32 ui32DevIndex);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex);
+
+#if !defined(USE_CODE)
+
+/*!
+******************************************************************************
+
+ @Function	PollForValueKM
+
+ @Description
+ Polls for a value to match a masked read of sysmem
+
+ @Input pui32LinMemAddr : CPU linear address of the mem to poll
+ @Input ui32Value : req'd value
+ @Input ui32Mask : Mask
+ @Input ui32Timeoutus : maximum total time to wait (us)
+ @Input ui32PollPeriodus : minimum delay between consecutive polls (us)
+ @Input bAllowPreemption : allow the polling loop to be preempted
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32*  pui32LinMemAddr,
+                                                    IMG_UINT32            ui32Value,
+                                                    IMG_UINT32            ui32Mask,
+                                                    IMG_UINT32            ui32Timeoutus,
+                                                    IMG_UINT32            ui32PollPeriodus,
+                                                    IMG_BOOL              bAllowPreemption);
+
+#endif /* !defined(USE_CODE) */
+
+
+#if defined (USING_ISR_INTERRUPTS)
+PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
+                                             IMG_UINT32 ui32Mask,
+                                             IMG_UINT32 ui32Waitus,
+                                             IMG_UINT32 ui32Tries);
+
+#endif /* #if defined (USING_ISR_INTERRUPTS) */
+
+/* The following functions don't really belong here (srvkm.h might be a better 
+ * place), but as they use the device data structures, this is the most convenient 
+ * place for them. */
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData);
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData);
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData);
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData);
+
+#if defined(__cplusplus)
+}
+#endif
+	
+#endif /* __DEVICE_H__ */
+
+/******************************************************************************
+ End of file (device.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/devicemem.h b/drivers/gpu/pvr/services4/srvkm/include/devicemem.h
new file mode 100644
index 0000000..00f8fe1
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/devicemem.h
@@ -0,0 +1,52 @@
+/*************************************************************************/ /*!
+@Title          KM internal device memory functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "img_defs.h"
+#include "img_types.h"
+#include "servicesext.h"
+
+#ifndef __DEVICEMEM_H__
+#define __DEVICEMEM_H__
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitDeviceMem(IMG_VOID);
+IMG_VOID IMG_CALLCONV PVRSRVDeInitDeviceMem(IMG_VOID);
+
+#endif /* __DEVICEMEM_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/include/dmabuf_sync.h b/drivers/gpu/pvr/services4/srvkm/include/dmabuf_sync.h
new file mode 100644
index 0000000..066bbee
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/dmabuf_sync.h
@@ -0,0 +1,69 @@
+/*************************************************************************/ /*!
+@Title          Services dma_buf synchronisation integration
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "img_defs.h"
+#include "img_types.h"
+#include "servicesint.h"
+
+#ifndef __DMABUF_SYNC_H__
+#define __DMABUF_SYNC_H__
+
+typedef struct _PVRSRV_DMABUF_SYNC_INFO_ {
+	PVRSRV_KERNEL_SYNC_INFO 		*psSyncInfo;
+	IMG_HANDLE				hUnique;
+	IMG_UINT32				ui32RefCount;
+	IMG_UINT64				ui64Stamp;
+} PVRSRV_DMABUF_SYNC_INFO;
+
+PVRSRV_ERROR PVRSRVDmaBufSyncAcquire(IMG_HANDLE hUnique,
+										IMG_HANDLE hPriv,
+										IMG_HANDLE hDevCookie,
+										IMG_HANDLE hDevMemContext,
+										PVRSRV_DMABUF_SYNC_INFO **ppsDmaBufSyncInfo);
+
+IMG_VOID PVRSRVDmaBufSyncRelease(PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo);
+
+static INLINE IMG_UINT64 DmaBufSyncGetStamp(PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo)
+{
+	return psDmaBufSyncInfo->ui64Stamp;
+}
+
+#endif /* __DMABUF_SYNC_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/include/handle.h b/drivers/gpu/pvr/services4/srvkm/include/handle.h
new file mode 100644
index 0000000..f636073
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/handle.h
@@ -0,0 +1,547 @@
+/*************************************************************************/ /*!
+@Title          Handle Manager API
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	Provide handle management
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+/*
+ * Handle API
+ * ----------
+ * The handle API is intended to provide handles for kernel resources,
+ * which can then be passed back to user space processes.
+ *
+ * The following functions comprise the API.  Each function takes a
+ * pointer to a PVRSRV_HANDLE_BASE strcture, one of which is allocated
+ * for each process, and stored in the per-process data area.  Use
+ * KERNEL_HANDLE_BASE for handles not allocated for a particular process,
+ * or for handles that need to be allocated before the PVRSRV_HANDLE_BASE
+ * structure for the process is available.
+ *
+ * PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType,
+ * 	PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+ *
+ * Allocate a handle phHandle, for the resource of type eType pointed to by
+ * pvData.
+ *
+ * For handles that have a definite lifetime, where the corresponding
+ * resource is explicitly created and destroyed, eFlag should be zero.
+ *
+ * If the resource is not explicitly created and destroyed, eFlag should be
+ * set to PVRSRV_HANDLE_ALLOC_FLAG_SHARED.  For a given process, the same
+ * handle will be returned each time a handle for the resource is allocated
+ * with the PVRSRV_HANDLE_ALLOC_FLAG_SHARED flag.
+ *
+ * If a particular resource may be referenced multiple times by a
+ * given process, setting eFlag to PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+ * will allow multiple handles to be allocated for the resource.
+ * Such handles cannot be found with PVRSRVFindHandle.
+ *
+ * PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType,
+ * 	PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+ *
+ * This function is similar to PVRSRVAllocHandle, except that the allocated
+ * handles are associated with a parent handle, hParent, that has been
+ * allocated previously.  Subhandles are automatically deallocated when their
+ * parent handle is dealloacted.
+ * Subhandles can be treated as ordinary handles.  For example, they may
+ * have subhandles of their own, and may be explicity deallocated using
+ * PVRSRVReleaseHandle (see below).
+ *
+ * PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Find the handle previously allocated for the resource pointed to by
+ * pvData, of type eType.  Handles allocated with the flag
+ * PVRSRV_HANDLE_ALLOC_FLAG_MULTI cannot be found using this
+ * function.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Given a handle for a resource of type eType, return the pointer to the
+ * resource.
+ *
+ * PVRSRV_ERROR PVRSRVLookuSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType,
+ * 	IMH_HANDLE hAncestor);
+ *
+ * Similar to PVRSRVLookupHandle, but checks the handle is a descendent
+ * of hAncestor.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+ *
+ * This function returns the resource pointer corresponding to the
+ * given handle, and the resource type in peType.  This function is
+ * intended for situations where a handle may be one of several types,
+ * but the type isn't known beforehand.
+ *
+ * PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Deallocate a handle of given type.
+ *
+ * PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * This function combines the functionality of PVRSRVLookupHandle and
+ * PVRSRVReleaseHandle, deallocating the handle after looking it up.
+ *
+ * PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Return the parent of a handle in *phParent, or IMG_NULL if the handle has
+ * no parent.
+ *
+ * PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_UINT32 ui32BatchSize)
+ *
+ * Allocate a new handle batch.  This preallocates ui32BatchSize handles.
+ * Batch mode simplifies the handling of handle allocation failures.
+ * The handle API is unchanged in batch mode, except that handles freed
+ * in batch mode will not be available for reallocation until the batch
+ * is committed or released (see below).
+ *
+ * PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+ * void PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+ *
+ * When handle allocation from a handle batch is complete, the
+ * batch must be committed by calling PVRSRVCommitHandleBatch.  If
+ * an error occurred, and none of the handles in the batch are no
+ * longer needed, PVRSRVReleaseHandleBatch must be called.
+ * The macros PVRSRVAllocHandleNR, and PVRSRVAllocSubHandleNR
+ * are defined for use in batch mode.  These work the same way
+ * as PVRSRVAllocHandle and PVRSRVAllocSubHandle, except that
+ * they don't return a value, relying on the fact that
+ * PVRSRVCommitHandleBatch will not commit any of the handles
+ * in a batch if there was an error allocating one of the
+ * handles in the batch.
+ *
+ * PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase,
+ * 	IMG_UINT32 ui32MaxHandle)
+ * Set the maximum handle number.  This is intended to restrict the
+ * handle range so that it will fit within a given field width.  For
+ * example, setting the maximum handle number to 0x7fffffff, would
+ * ensure the handles would fit within a 31 bit width field.  This
+ * facility should be used with caution, as it restricts the number of
+ * handles that can be allocated.
+ *
+ * IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+ * Return the maximum handle number, or 0 if the setting of a limit
+ * is not supported.
+ *
+ * PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+ * Allows unused handle space to be reclaimed, by calling
+ * PVRSRVPurgeHandles.  Note that allocating handles may have a
+ * higher overhead if purging is enabled.
+ *
+ * PVRSRV_ERROR PVRSRVPurgeHandles((PVRSRV_HANDLE_BASE *psBase)
+ * Purge handles for a handle base that has purging enabled.
+ */
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+typedef enum
+{
+	PVRSRV_HANDLE_TYPE_NONE = 0,
+	PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+	PVRSRV_HANDLE_TYPE_DEV_NODE,
+	PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+	PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+	PVRSRV_HANDLE_TYPE_MEM_INFO,
+	PVRSRV_HANDLE_TYPE_SYNC_INFO,
+	PVRSRV_HANDLE_TYPE_DISP_INFO,
+	PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+	PVRSRV_HANDLE_TYPE_BUF_INFO,
+	PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+	PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+	PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+	PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+	PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+	PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+	PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+	PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+	PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+	PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+	PVRSRV_HANDLE_TYPE_MMAP_INFO,
+	PVRSRV_HANDLE_TYPE_SOC_TIMER,
+	PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ,
+	PVRSRV_HANDLE_TYPE_RESITEM_INFO
+} PVRSRV_HANDLE_TYPE;
+
+typedef enum
+{
+	/* No flags */
+	PVRSRV_HANDLE_ALLOC_FLAG_NONE = 		0,
+	/* Share a handle that already exists for a given data pointer */
+	PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 		0x01,
+	/* Muliple handles can point at the given data pointer */
+	PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 		0x02,
+	/* Subhandles are allocated in a private handle space */
+	PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 		0x04
+} PVRSRV_HANDLE_ALLOC_FLAG;
+
+struct _PVRSRV_HANDLE_BASE_;
+typedef struct _PVRSRV_HANDLE_BASE_ PVRSRV_HANDLE_BASE;
+
+#if defined(PVR_SECURE_HANDLES)
+extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define	KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle);
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
+
+#else	/* #if defined (PVR_SECURE_HANDLES) */
+
+#define KERNEL_HANDLE_BASE IMG_NULL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(eFlag);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*phHandle = pvData;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(eFlag);
+	PVR_UNREFERENCED_PARAMETER(hParent);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*phHandle = pvData;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*phHandle = pvData;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandleAnyType)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	/*
+	 * Unlike the other functions here, the returned results will need
+	 * to be handled differently for the secure and non-secure cases.
+	 */
+	*peType = PVRSRV_HANDLE_TYPE_NONE;
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(eType);
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(hAncestor);
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetParentHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(hHandle);
+
+	*phParent = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupAndReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	*ppvData = hHandle;
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+	PVR_UNREFERENCED_PARAMETER(hHandle);
+	PVR_UNREFERENCED_PARAMETER(eType);
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVNewHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(ui32BatchSize);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCommitHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandleBatch)
+#endif
+static INLINE
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSetMaxHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+	PVR_UNREFERENCED_PARAMETER(ui32MaxHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetMaxHandle)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return 0;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVEnableHandlePurging)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPurgeHandles)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+	*ppsBase = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFreeHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psBase);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleDeInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+	return PVRSRV_OK;
+}
+
+#endif	/* #if defined (PVR_SECURE_HANDLES) */
+
+/*
+ * Versions of PVRSRVAllocHandle and PVRSRVAllocSubHandle with no return
+ * values.  Intended for use with batched handle allocation, relying on
+ * CommitHandleBatch to detect handle allocation errors.
+ */
+#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
+	(IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent) \
+	(IMG_VOID)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, eFlag, hParent)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __HANDLE_H__ */
+
+/******************************************************************************
+ End of file (handle.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/hash.h b/drivers/gpu/pvr/services4/srvkm/include/hash.h
new file mode 100644
index 0000000..1ed6fd0
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/hash.h
@@ -0,0 +1,277 @@
+/*************************************************************************/ /*!
+@Title          Self scaling hash tables
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements simple self scaling hash tables.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include "img_types.h"
+#include "osfunc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * Keys passed to the comparsion function are only guaranteed to
+ * be aligned on an IMG_UINTPTR_T boundary. 
+ */
+typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+typedef struct _HASH_TABLE_ HASH_TABLE;
+
+typedef PVRSRV_ERROR (*HASH_pfnCallback) (
+	IMG_UINTPTR_T k,
+	IMG_UINTPTR_T v
+);
+
+/*!
+******************************************************************************
+    @Function       HASH_Func_Default
+
+    @Description    Hash function intended for hashing keys composed of
+                    IMG_UINTPTR_T arrays.
+	                	
+    @Input          uKeySize - the size of the hash key, in bytes.
+    @Input          pKey - a pointer to the key to hash.
+    @Input          uHashTabLen - the length of the hash table. 
+
+    @Return         The hash value.
+******************************************************************************/
+IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+
+/*!
+******************************************************************************
+    @Function       HASH_Key_Comp_Default
+
+    @Description    Compares keys composed of IMG_UINTPTR_T arrays.
+	                	
+    @Input          uKeySize - the size of the hash key, in bytes.
+    @Input          pKey1 - pointer to first hash key to compare.
+    @Input          pKey2 - pointer to second hash key to compare.
+
+    @Return         IMG_TRUE  - the keys match.
+                    IMG_FALSE - the keys don't match.
+******************************************************************************/
+IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+/*!
+******************************************************************************
+    @Function       HASH_Create_Extended
+
+    @Description    Create a self scaling hash table, using the supplied
+                    key size, and the supllied hash and key comparsion
+                    functions.
+	                	
+    @Input          uInitialLen - initial and minimum length of the
+                        hash table, where the length refers to the number
+                        of entries in the hash table, not its size in
+                        bytes.
+    @Input          uKeySize - the size of the key, in bytes.
+    @Input          pfnHashFunc - pointer to hash function.
+    @Input          pfnKeyComp - pointer to key comparsion function.
+
+    @Return         IMG_NULL or hash table handle.
+******************************************************************************/
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+
+/*!
+******************************************************************************
+    @Function       HASH_Create
+
+    @Description    Create a self scaling hash table with a key
+                    consisting of a single IMG_UINTPTR_T, and using
+                    the default hash and key comparison functions.
+	                	
+    @Input          uInitialLen - initial and minimum length of the
+                        hash table, where the length refers to the
+                        number of entries in the hash table, not its size
+                        in bytes.
+
+    @Return         IMG_NULL or hash table handle.
+******************************************************************************/
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+
+/*!
+******************************************************************************
+    @Function       HASH_Delete
+
+    @Description    Delete a hash table created by HASH_Create_Extended or
+                    HASH_Create.  All entries in the table must have been
+                    removed before calling this function.
+	                	
+    @Input          pHash - hash table
+
+    @Return         None
+******************************************************************************/
+IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+
+/*!
+******************************************************************************
+    @Function       HASH_Insert_Extended
+
+    @Description    Insert a key value pair into a hash table created
+                    with HASH_Create_Extended.
+	                	
+    @Input          pHash - the hash table.
+    @Input          pKey - pointer to the key.
+    @Input          v - the value associated with the key.
+
+    @Return         IMG_TRUE - success.
+                    IMG_FALSE - failure.
+******************************************************************************/
+IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+
+/*!
+******************************************************************************
+    @Function       HASH_Insert
+
+    @Description    Insert a key value pair into a hash table created with
+                    HASH_Create.
+	                	
+    @Input          pHash - the hash table.
+    @Input          k - the key value.
+    @Input          v - the value associated with the key.
+
+    @Return         IMG_TRUE - success.
+                    IMG_FALSE - failure.
+******************************************************************************/
+IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+
+/*!
+******************************************************************************
+    @Function       HASH_Remove_Extended
+
+    @Description    Remove a key from a hash table created with
+                    HASH_Create_Extended.
+	                	
+    @Input          pHash - the hash table.
+    @Input          pKey - pointer to key.
+
+    @Return         0 if the key is missing, or the value associated
+                    with the key.
+******************************************************************************/
+IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+
+/*!
+******************************************************************************
+    @Function       HASH_Remove
+
+    @Description    Remove a key value pair from a hash table created
+                    with HASH_Create.
+	                	
+    @Input          pHash - the hash table
+    @Input          k - the key
+
+    @Return         0 if the key is missing, or the value associated
+                    with the key.
+******************************************************************************/
+IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+/*!
+******************************************************************************
+    @Function       HASH_Retrieve_Extended
+
+    @Description    Retrieve a value from a hash table created with
+                    HASH_Create_Extended.
+	                	
+    @Input          pHash - the hash table.
+    @Input          pKey - pointer to the key.
+
+    @Return         0 if the key is missing, or the value associated with
+                    the key.
+******************************************************************************/
+IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+
+/*!
+******************************************************************************
+    @Function       HASH_Retrieve
+
+    @Description    Retrieve a value from a hash table created with
+                    HASH_Create.
+	                	
+    @Input          pHash - the hash table
+    @Input          k - the key
+
+    @Return         0 if the key is missing, or the value associated with
+                    the key.
+******************************************************************************/
+IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+/*!
+******************************************************************************
+    @Function       HASH_Interate
+
+    @Description    Iterate over every entry in the hash table
+
+    @Input          pHash - the old hash table
+    @Input          HASH_pfnCallback - the size of the old hash table
+
+    @Return         Callback error if any, otherwise PVRSRV_OK
+******************************************************************************/
+PVRSRV_ERROR HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback);
+
+#ifdef HASH_TRACE
+/*!
+******************************************************************************
+    @Function       HASH_Dump
+
+    @Description    Dump out some information about a hash table.
+	                	
+    @Input          pHash - the hash table
+
+    @Return         None
+******************************************************************************/
+IMG_VOID HASH_Dump (HASH_TABLE *pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _HASH_H_ */
+
+/******************************************************************************
+ End of file (hash.h)
+******************************************************************************/
+
+
diff --git a/drivers/gpu/pvr/services4/srvkm/include/ion_sync.h b/drivers/gpu/pvr/services4/srvkm/include/ion_sync.h
new file mode 100644
index 0000000..8600a19
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/ion_sync.h
@@ -0,0 +1,73 @@
+/*************************************************************************/ /*!
+@Title          Services Ion synchronisation integration
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "img_defs.h"
+#include "img_types.h"
+#include "servicesint.h"
+
+#ifndef __ION_SYNC_H__
+#define __ION_SYNC_H__
+
+typedef struct _PVRSRV_ION_SYNC_INFO_ {
+	PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+	IMG_HANDLE				hUnique;
+	IMG_UINT32				ui32RefCount;
+	IMG_UINT64				ui64Stamp;
+} PVRSRV_ION_SYNC_INFO;
+
+PVRSRV_ERROR PVRSRVIonBufferSyncAcquire(IMG_HANDLE hUnique,
+										IMG_HANDLE hDevCookie,
+										IMG_HANDLE hDevMemContext,
+										PVRSRV_ION_SYNC_INFO **ppsIonSyncInfo);
+
+IMG_VOID PVRSRVIonBufferSyncRelease(PVRSRV_ION_SYNC_INFO *psIonSyncInfo);
+
+static INLINE PVRSRV_KERNEL_SYNC_INFO *IonBufferSyncGetKernelSyncInfo(PVRSRV_ION_SYNC_INFO *psIonSyncInfo)
+{
+	return psIonSyncInfo->psSyncInfo;
+}
+
+static INLINE IMG_UINT64 IonBufferSyncGetStamp(PVRSRV_ION_SYNC_INFO *psIonSyncInfo)
+{
+	return psIonSyncInfo->ui64Stamp;
+}
+
+#endif /* __ION_SYNC_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/include/lists.h b/drivers/gpu/pvr/services4/srvkm/include/lists.h
new file mode 100644
index 0000000..31f5409
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/lists.h
@@ -0,0 +1,353 @@
+/*************************************************************************/ /*!
+@Title          Linked list shared functions templates.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Definition of the linked list function templates.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __LISTS_UTILS__
+#define __LISTS_UTILS__
+
+/* instruct QAC to ignore warnings about the following custom formatted macros */
+/* PRQA S 0881,3410 ++ */
+#include <stdarg.h>
+#include "img_types.h"
+
+/*
+ - USAGE -
+
+ The list functions work with any structure that provides the fields psNext and
+ ppsThis. In order to make a function available for a given type, it is required
+ to use the funcion template macro that creates the actual code.
+
+ There are 4 main types of functions:
+ - INSERT	: given a pointer to the head pointer of the list and a pointer to
+ 			  the node, inserts it as the new head.
+ - REMOVE	: given a pointer to a node, removes it from its list.
+ - FOR EACH	: apply a function over all the elements of a list.
+ - ANY		: apply a function over the elements of a list, until one of them
+ 			  return a non null value, and then returns it.
+
+ The two last functions can have a variable argument form, with allows to pass
+ additional parameters to the callback function. In order to do this, the
+ callback function must take two arguments, the first is the current node and
+ the second is a list of variable arguments (va_list).
+
+ The ANY functions have also another for wich specifies the return type of the
+ callback function and the default value returned by the callback function.
+
+*/
+
+/*!
+******************************************************************************
+    @Function       List_##TYPE##_ForEach
+
+    @Description    Apply a callback function to all the elements of a list.
+
+    @Input          psHead - the head of the list to be processed.
+    @Input          pfnCallBack - the function to be applied to each element 
+                        of the list.
+
+    @Return         None
+******************************************************************************/
+#define DECLARE_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+	while(psHead)\
+	{\
+		pfnCallBack(psHead);\
+		psHead = psHead->psNext;\
+	}\
+}
+
+
+#define DECLARE_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...) \
+{\
+	va_list ap;\
+	while(psHead)\
+	{\
+		va_start(ap, pfnCallBack);\
+		pfnCallBack(psHead, ap);\
+		psHead = psHead->psNext;\
+		va_end(ap);\
+	}\
+}
+
+
+/*!
+******************************************************************************
+    @Function       List_##TYPE##_Any
+
+    @Description    Applies a callback function to the elements of a list until 
+                    the function returns a non null value, then returns it.
+
+    @Input          psHead - the head of the list to be processed.
+    @Input          pfnCallBack - the function to be applied to each element 
+                    of the list.
+
+    @Return         None
+******************************************************************************/
+#define DECLARE_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))\
+{ \
+	IMG_VOID *pResult;\
+	TYPE *psNextNode;\
+	pResult = IMG_NULL;\
+	psNextNode = psHead;\
+	while(psHead && !pResult)\
+	{\
+		psNextNode = psNextNode->psNext;\
+		pResult = pfnCallBack(psHead);\
+		psHead = psNextNode;\
+	}\
+	return pResult;\
+}
+
+
+/*with variable arguments, that will be passed as a va_list to the callback function*/
+
+#define DECLARE_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+	va_list ap;\
+	TYPE *psNextNode;\
+	IMG_VOID* pResult = IMG_NULL;\
+	while(psHead && !pResult)\
+	{\
+		psNextNode = psHead->psNext;\
+		va_start(ap, pfnCallBack);\
+		pResult = pfnCallBack(psHead, ap);\
+		va_end(ap);\
+		psHead = psNextNode;\
+	}\
+	return pResult;\
+}
+
+/*those ones are for extra type safety, so there's no need to use castings for the results*/
+
+#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))\
+{ \
+	RTYPE result;\
+	TYPE *psNextNode;\
+	result = CONTINUE;\
+	psNextNode = psHead;\
+	while(psHead && result == CONTINUE)\
+	{\
+		psNextNode = psNextNode->psNext;\
+		result = pfnCallBack(psHead);\
+		psHead = psNextNode;\
+	}\
+	return result;\
+}
+
+
+#define DECLARE_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+	va_list ap;\
+	TYPE *psNextNode;\
+	RTYPE result = CONTINUE;\
+	while(psHead && result == CONTINUE)\
+	{\
+		psNextNode = psHead->psNext;\
+		va_start(ap, pfnCallBack);\
+		result = pfnCallBack(psHead, ap);\
+		va_end(ap);\
+		psHead = psNextNode;\
+	}\
+	return result;\
+}
+
+
+/*!
+******************************************************************************
+    @Function       List_##TYPE##_Remove
+
+    @Description    Removes a given node from the list.
+
+    @Input          psNode - the pointer to the node to be removed.
+
+    @Return         None
+******************************************************************************/
+#define DECLARE_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
+
+#define IMPLEMENT_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
+{\
+	(*psNode->ppsThis)=psNode->psNext;\
+	if(psNode->psNext)\
+	{\
+		psNode->psNext->ppsThis = psNode->ppsThis;\
+	}\
+}
+
+/*!
+******************************************************************************
+    @Function       List_##TYPE##_Insert
+
+    @Description    Inserts a given node at the beginnning of the list.
+
+    @Input          psHead - The pointer to the pointer to the head node.
+    @Input          psNode - The pointer to the node to be inserted.
+
+    @Return         None
+******************************************************************************/
+#define DECLARE_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+	psNewNode->ppsThis = ppsHead;\
+	psNewNode->psNext = *ppsHead;\
+	*ppsHead = psNewNode;\
+	if(psNewNode->psNext)\
+	{\
+		psNewNode->psNext->ppsThis = &(psNewNode->psNext);\
+	}\
+}
+
+/*!
+******************************************************************************
+    @Function       List_##TYPE##_Reverse
+
+    @Description    Reverse a list in place
+
+    @Input          ppsHead - The pointer to the pointer to the head node.
+					
+    @Return         None
+******************************************************************************/
+#define DECLARE_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)
+
+#define IMPLEMENT_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)\
+{\
+    TYPE *psTmpNode1; \
+    TYPE *psTmpNode2; \
+    TYPE *psCurNode; \
+	psTmpNode1 = IMG_NULL; \
+	psCurNode = *ppsHead; \
+	while(psCurNode) { \
+    	psTmpNode2 = psCurNode->psNext; \
+        psCurNode->psNext = psTmpNode1; \
+		psTmpNode1 = psCurNode; \
+		psCurNode = psTmpNode2; \
+		if(psCurNode) \
+		{ \
+			psTmpNode1->ppsThis = &(psCurNode->psNext); \
+		} \
+		else \
+		{ \
+			psTmpNode1->ppsThis = ppsHead;		\
+		} \
+	} \
+	*ppsHead = psTmpNode1; \
+}
+
+#define IS_LAST_ELEMENT(x) ((x)->psNext == IMG_NULL)
+
+#include "services_headers.h"
+
+DECLARE_LIST_ANY_VA(BM_HEAP);
+DECLARE_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+DECLARE_LIST_REMOVE(BM_HEAP);
+DECLARE_LIST_INSERT(BM_HEAP);
+
+DECLARE_LIST_ANY_VA(BM_CONTEXT);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(BM_CONTEXT);
+DECLARE_LIST_REMOVE(BM_CONTEXT);
+DECLARE_LIST_INSERT(BM_CONTEXT);
+
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+DECLARE_LIST_ANY_2(PVRSRV_KERNEL_SYNC_INFO, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_KERNEL_SYNC_INFO);
+DECLARE_LIST_REMOVE(PVRSRV_KERNEL_SYNC_INFO);
+
+#undef DECLARE_LIST_ANY_2
+#undef DECLARE_LIST_ANY_VA
+#undef DECLARE_LIST_ANY_VA_2
+#undef DECLARE_LIST_FOR_EACH
+#undef DECLARE_LIST_FOR_EACH_VA
+#undef DECLARE_LIST_INSERT
+#undef DECLARE_LIST_REMOVE
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+
+#endif
+
+/* re-enable warnings */
+/* PRQA S 0881,3410 -- */
diff --git a/drivers/gpu/pvr/services4/srvkm/include/metrics.h b/drivers/gpu/pvr/services4/srvkm/include/metrics.h
new file mode 100644
index 0000000..18079cb
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/metrics.h
@@ -0,0 +1,146 @@
+/*************************************************************************/ /*!
+@Title          Time measurement interface.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _METRICS_
+#define _METRICS_
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(DEBUG) || defined(TIMING)
+
+
+typedef struct 
+{
+	IMG_UINT32 ui32Start;
+	IMG_UINT32 ui32Stop;
+	IMG_UINT32 ui32Total;
+	IMG_UINT32 ui32Count;
+} Temporal_Data;
+
+extern Temporal_Data asTimers[]; 
+
+extern IMG_UINT32 PVRSRVTimeNow(IMG_VOID);
+extern IMG_VOID   PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo);
+extern IMG_VOID   PVRSRVOutputMetricTotals(IMG_VOID);
+
+
+#define PVRSRV_TIMER_DUMMY				0
+
+#define PVRSRV_TIMER_EXAMPLE_1			1
+#define PVRSRV_TIMER_EXAMPLE_2			2
+
+
+#define PVRSRV_NUM_TIMERS		(PVRSRV_TIMER_EXAMPLE_2 + 1)
+
+#define PVRSRV_TIME_START(X)	{ \
+									asTimers[X].ui32Count += 1; \
+									asTimers[X].ui32Count |= 0x80000000L; \
+									asTimers[X].ui32Start = PVRSRVTimeNow(); \
+									asTimers[X].ui32Stop  = 0; \
+								}
+
+#define PVRSRV_TIME_SUSPEND(X)	{ \
+									asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+								}
+
+#define PVRSRV_TIME_RESUME(X)	{ \
+									asTimers[X].ui32Start = PVRSRVTimeNow(); \
+								}
+
+#define PVRSRV_TIME_STOP(X)		{ \
+									asTimers[X].ui32Stop  += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+									asTimers[X].ui32Total += asTimers[X].ui32Stop; \
+									asTimers[X].ui32Count &= 0x7FFFFFFFL; \
+								}
+
+#define PVRSRV_TIME_RESET(X)	{ \
+									asTimers[X].ui32Start = 0; \
+									asTimers[X].ui32Stop  = 0; \
+									asTimers[X].ui32Total = 0; \
+									asTimers[X].ui32Count = 0; \
+								}
+
+
+#if defined(__sh__)
+
+#define TST_REG   ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM)) 	// timer start register
+
+#define TCOR_2    ((volatile IMG_UINT *)  (psDevInfo->pvSOCRegsBaseKM+28))	// timer constant register_2
+#define TCNT_2    ((volatile IMG_UINT *)  (psDevInfo->pvSOCRegsBaseKM+32))	// timer counter register_2
+#define TCR_2     ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))	// timer control register_2
+
+#define TIMER_DIVISOR  4
+
+#endif /* defined(__sh__) */
+
+
+
+#else /* defined(DEBUG) || defined(TIMING) */
+
+
+
+#define PVRSRV_TIME_START(X)
+#define PVRSRV_TIME_SUSPEND(X)
+#define PVRSRV_TIME_RESUME(X)
+#define PVRSRV_TIME_STOP(X)
+#define PVRSRV_TIME_RESET(X)
+
+#define PVRSRVSetupMetricTimers(X)
+#define PVRSRVOutputMetricTotals()
+
+
+
+#endif /* defined(DEBUG) || defined(TIMING) */
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif /* _METRICS_ */
+
+/**************************************************************************
+ End of file (metrics.h)
+**************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/osfunc.h b/drivers/gpu/pvr/services4/srvkm/include/osfunc.h
new file mode 100644
index 0000000..61d4be3
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/osfunc.h
@@ -0,0 +1,802 @@
+/*************************************************************************/ /*!
+@Title          OS functions header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    OS specific API definitions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG		1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/hardirq.h>
+#include <linux/string.h>
+#if defined(__arm__) || defined(__aarch64__)
+#include <asm/memory.h>
+#endif
+#endif
+
+
+/* setup conditional pageable / non-pageable select */
+	/* Other OSs only need pageable */
+	#define PVRSRV_PAGEABLE_SELECT		PVRSRV_OS_PAGEABLE_HEAP
+
+/******************************************************************************
+ * Static defines
+ *****************************************************************************/
+#define KERNEL_ID			0xffffffffL
+#define POWER_MANAGER_ID	0xfffffffeL
+#define ISR_ID				0xfffffffdL
+#define TIMER_ID			0xfffffffcL
+
+
+#define HOST_PAGESIZE			OSGetPageSize
+#define HOST_PAGEMASK			(HOST_PAGESIZE()-1)
+#define HOST_PAGEALIGN(addr)	(((addr) + HOST_PAGEMASK) & ~HOST_PAGEMASK)
+
+/******************************************************************************
+ *	Host memory heaps
+ *****************************************************************************/
+#define PVRSRV_OS_HEAP_MASK			0xf /* host heap flags mask */
+#define PVRSRV_OS_PAGEABLE_HEAP		0x1 /* allocation pageable */
+#define PVRSRV_OS_NON_PAGEABLE_HEAP	0x2 /* allocation non pageable */
+#if defined (__linux__) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define PVRSRV_SWAP_BUFFER_ALLOCATION	0x4 /* allocation for swap buffer */
+#else
+#define PVRSRV_SWAP_BUFFER_ALLOCATION	0x0
+#endif
+
+#if defined (PVRSRV_DEVMEM_TIME_STATS)
+IMG_UINT64 OSClockMonotonicus(IMG_VOID);
+#endif
+IMG_UINT32 OSClockus(IMG_VOID);
+IMG_UINT32 OSGetPageSize(IMG_VOID);
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+								 IMG_UINT32 ui32Irq,
+								 IMG_CHAR *pszISRName,
+								 IMG_VOID *pvDeviceNode);
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq);
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData);
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE, IMG_VOID* pvLinAddr);
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T uiSize);
+IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
+IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE hBMHandle, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+/* Some terminology:
+ *
+ *  FLUSH		Flush w/ invalidate
+ *  CLEAN		Flush w/o invalidate
+ *  INVALIDATE	Invalidate w/o flush
+ */
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID);
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length);
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+								IMG_UINT32 ui32ByteOffset,
+								IMG_VOID *pvRangeAddrStart,
+								IMG_UINT32 ui32Length);
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+									 IMG_UINT32 ui32ByteOffset,
+									 IMG_VOID *pvRangeAddrStart,
+									 IMG_UINT32 ui32Length);
+
+#else /* defined(__linux__) && defined(__KERNEL__) */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSFlushCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSCleanCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+											  IMG_UINT32 ui32ByteOffset,
+											  IMG_VOID *pvRangeAddrStart,
+											  IMG_UINT32 ui32Length)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+	PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+	PVR_UNREFERENCED_PARAMETER(ui32Length);
+	return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+											  IMG_UINT32 ui32ByteOffset,
+											  IMG_VOID *pvRangeAddrStart,
+											  IMG_UINT32 ui32Length)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+	PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+	PVR_UNREFERENCED_PARAMETER(ui32Length);
+	return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSInvalidateCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+												   IMG_UINT32 ui32ByteOffset,
+												   IMG_VOID *pvRangeAddrStart,
+												   IMG_UINT32 ui32Length)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+	PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+	PVR_UNREFERENCED_PARAMETER(ui32Length);
+	return IMG_FALSE;
+}
+
+#endif /* defined(__linux__) && defined(__KERNEL__) */
+
+#if defined(__linux__) || defined(__QNXNTO__)
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+									IMG_VOID *pvCpuVAddr, 
+									IMG_SIZE_T uBytes,
+									IMG_UINT32 ui32Flags, 
+									IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+									IMG_SIZE_T uBytes,
+									IMG_UINT32 ui32Flags,
+									IMG_HANDLE hOSMemHandle);
+#else	/* defined(__linux__) */
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+													IMG_VOID *pvCpuVAddr,
+													IMG_SIZE_T uBytes,
+													IMG_UINT32 ui32Flags,
+													IMG_HANDLE *phOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+	PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+													IMG_SIZE_T uBytes,
+													IMG_UINT32 ui32Flags,
+													IMG_HANDLE hOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif	/* defined(__linux__) */
+
+
+#if  defined(__linux__) || defined(__QNXNTO__)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+#if defined(__linux__) || defined(__QNXNTO__) 
+	*ppvCpuVAddr = IMG_NULL;
+	return OSRegisterDiscontigMem(pBasePAddr, *ppvCpuVAddr, uBytes, ui32Flags, phOSMemHandle);	
+#else
+	extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
+
+	/*
+	 * On uITRON we know:
+	 * 1. We will only be called with a non-contig physical if we
+	 *    already have a contiguous CPU linear
+	 * 2. There is a one->one mapping of CpuPAddr -> CpuVAddr
+	 * 3. Looking up the first CpuPAddr will find the first CpuVAddr
+	 * 4. We don't need to unmap
+	 */
+
+	return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), uBytes, ui32Flags, IMG_NULL, ppvCpuVAddr, phOSMemHandle);
+#endif	
+}
+
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+#if defined(__linux__) || defined(__QNXNTO__) 
+	OSUnRegisterDiscontigMem(pvCpuVAddr, uBytes, ui32Flags, hOSMemHandle);
+#endif
+	/* We don't need to unmap */
+	return PVRSRV_OK;
+}
+#else	/* defined(__linux__) */
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+	PVR_UNREFERENCED_PARAMETER(uBytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(ppvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T uBytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+	PVR_UNREFERENCED_PARAMETER(uBytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+	return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif	/* defined(__linux__) */
+
+PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+							IMG_VOID *pvCpuVAddr,
+							IMG_SIZE_T uBytes,
+							IMG_UINT32 ui32Flags,
+							IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterMem(IMG_VOID *pvCpuVAddr,
+							IMG_SIZE_T uBytes,
+							IMG_UINT32 ui32Flags,
+							IMG_HANDLE hOSMemHandle);
+
+
+
+#if defined(__linux__) || defined(__QNXNTO__)
+PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+							   IMG_UINTPTR_T uByteOffset,
+							   IMG_SIZE_T uBytes,
+							   IMG_UINT32 ui32Flags,
+							   IMG_HANDLE *phOSMemHandleRet);
+PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetSubMemHandle)
+#endif
+static INLINE PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+											 IMG_UINTPTR_T uByteOffset,
+											 IMG_SIZE_T uBytes,
+											 IMG_UINT32 ui32Flags,
+											 IMG_HANDLE *phOSMemHandleRet)
+{
+	PVR_UNREFERENCED_PARAMETER(uByteOffset);
+	PVR_UNREFERENCED_PARAMETER(uBytes);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+	*phOSMemHandleRet = hOSMemHandle;
+	return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_UNREFERENCED_PARAMETER(ui32Flags);
+	return PVRSRV_OK;
+}
+#endif
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID);
+#if defined (MEM_TRACK_INFO_DEBUG)
+IMG_UINT32 OSGetCurrentTimeInUSecsKM(IMG_VOID);
+#endif
+IMG_UINTPTR_T OSGetCurrentThreadID( IMG_VOID );
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T uSize);
+
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, IMG_UINT32 ui32PageSize,
+							   IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength, IMG_HANDLE hBMHandle, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+
+
+/*---------------------
+The set of macros below follows this pattern:
+
+f(x) = if F -> f2(g(x))
+       else -> g(x)
+
+g(x) = if G -> g2(h(x))
+       else -> h(x)
+
+h(x) = ...
+
+-----------------------*/
+
+/*If level 3 wrapper is enabled, we add a PVR_TRACE and call the next level, else just call the next level*/
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+	#define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
+		(PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", (unsigned long)size)), \
+			OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+
+	#define OSAllocPages(flags, size, pageSize, privdata, privdatalength, bmhandle, linAddr, pageAlloc) \
+		(PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", (unsigned long)size)), \
+			OSAllocPages_Impl(flags, size, pageSize, privdata, privdatalength, bmhandle, linAddr, pageAlloc))
+		
+	#define OSFreeMem(flags, size, linAddr, blockAlloc) \
+		(PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%p)", linAddr)), \
+			OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+#else
+	#define OSAllocMem(flags, size, linAddr, blockAlloc, logString) \
+		OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+	
+	#define OSAllocPages OSAllocPages_Impl
+	
+	#define OSFreeMem(flags, size, linAddr, blockAlloc) \
+			OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+#endif
+ 
+/*If level 2 wrapper is enabled declare the function,
+else alias to level 1 wrapper, else the wrapper function will be used*/
+#ifdef PVRSRV_DEBUG_OS_MEMORY
+
+	PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+										IMG_UINT32 ui32Size,
+										IMG_PVOID *ppvCpuVAddr,
+										IMG_HANDLE *phBlockAlloc,
+										IMG_CHAR *pszFilename,
+										IMG_UINT32 ui32Line);
+	
+	PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+									 IMG_UINT32 ui32Size,
+									 IMG_PVOID pvCpuVAddr,
+									 IMG_HANDLE hBlockAlloc,
+									 IMG_CHAR *pszFilename,
+									 IMG_UINT32 ui32Line);
+
+
+	typedef struct
+	{	
+		IMG_UINT8 sGuardRegionBefore[8];
+		IMG_CHAR sFileName[128];
+		IMG_UINT32 uLineNo;
+		IMG_SIZE_T uSize;
+		IMG_SIZE_T uSizeParityCheck;
+		enum valid_tag
+		{	isFree = 0x277260FF,
+			isAllocated = 0x260511AA
+		} eValid;
+	} OSMEM_DEBUG_INFO;
+	
+	#define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
+	#define TEST_BUFFER_PADDING_AFTER  (8)
+	#define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
+#else
+	#define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
+	#define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
+#endif
+ 
+/*If level 1 wrapper is enabled declare the functions with extra parameters
+else alias to level 0 and declare the functions without the extra debugging parameters*/
+#if (defined(__linux__) || defined(__QNXNTO__)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+	PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+	PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+	
+	#define OSAllocMem_Debug_Linux_Memory_Allocations OSAllocMem_Impl
+	#define OSFreeMem_Debug_Linux_Memory_Allocations OSFreeMem_Impl
+#else
+	PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc);
+	PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc);
+	
+	#define OSAllocMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+		OSAllocMem_Impl(flags, size, addr, blockAlloc)
+	#define OSFreeMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+		OSFreeMem_Impl(flags, size, addr, blockAlloc)
+#endif
+
+
+#if defined(__linux__) || defined(__QNXNTO__)
+IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINTPTR_T uiByteOffset);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleToCpuPAddr)
+#endif
+static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE hOSMemHandle, IMG_UINTPTR_T uiByteOffset)
+{
+	IMG_CPU_PHYADDR sCpuPAddr;
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	PVR_UNREFERENCED_PARAMETER(uiByteOffset);
+	sCpuPAddr.uiAddr = 0;
+	return sCpuPAddr;
+}
+#endif
+
+#if defined(__linux__)
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleIsPhysContig)
+#endif
+static INLINE IMG_BOOL OSMemHandleIsPhysContig(IMG_HANDLE hOSMemHandle)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+	return IMG_FALSE;
+}
+#endif
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
+IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T uSize, const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+#define OSStringLength(pszString) strlen(pszString)
+
+PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName,
+								 PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
+											IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
+											IMG_HANDLE hOSEventKM);
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T uSize, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T uSize, IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr);
+
+IMG_PVOID MapUserFromKernel(IMG_PVOID pvLinAddrKM,IMG_SIZE_T uSize,IMG_HANDLE *phMemBlock);
+IMG_PVOID OSMapHWRegsIntoUserSpace(IMG_HANDLE hDevCookie, IMG_SYS_PHYADDR sRegAddr, IMG_UINT32 ulSize, IMG_PVOID *ppvProcess);
+IMG_VOID  OSUnmapHWRegsFromUserSpace(IMG_HANDLE hDevCookie, IMG_PVOID pvUserAddr, IMG_PVOID pvProcess);
+
+IMG_VOID  UnmapUserFromKernel(IMG_PVOID pvLinAddrUM, IMG_SIZE_T uSize, IMG_HANDLE hMemBlock);
+
+PVRSRV_ERROR OSMapPhysToUserSpace(IMG_HANDLE hDevCookie,
+								  IMG_SYS_PHYADDR sCPUPhysAddr,
+								  IMG_SIZE_T uiSizeInBytes,
+								  IMG_UINT32 ui32CacheFlags,
+								  IMG_PVOID *ppvUserAddr,
+								  IMG_SIZE_T *puiActualSize,
+								  IMG_HANDLE hMappingHandle);
+
+PVRSRV_ERROR OSUnmapPhysToUserSpace(IMG_HANDLE hDevCookie,
+									IMG_PVOID pvUserAddr,
+									IMG_PVOID pvProcess);
+
+PVRSRV_ERROR OSLockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSUnlockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+
+#if !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__)
+PVRSRV_ERROR OSLockResourceAndBlockMISR(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSUnlockResourceAndUnblockMISR(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+#endif /* !defined(PVR_LINUX_USING_WORKQUEUES) && defined(__linux__) */
+
+IMG_BOOL OSIsResourceLocked(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource);
+PVRSRV_ERROR OSDestroyResource(PVRSRV_RESOURCE *psResource);
+IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+#define OSPowerLockWrap SysPowerLockWrap
+#define OSPowerLockUnwrap SysPowerLockUnwrap
+#else
+/******************************************************************************
+ @Function	OSPowerLockWrap
+
+ @Description	OS-specific wrapper around the power lock
+
+ @Input bTryLock - don't block on lock contention
+
+ @Return	PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock);
+
+/******************************************************************************
+ @Function	OSPowerLockUnwrap
+
+ @Description	OS-specific wrapper around the power unlock
+
+ @Return	IMG_VOID
+******************************************************************************/
+IMG_VOID OSPowerLockUnwrap(IMG_VOID);
+#endif /* SYS_CUSTOM_POWERLOCK_WRAP */
+
+/*!
+******************************************************************************
+
+ @Function OSWaitus
+ 
+ @Description 
+    This function implements a busy wait of the specified microseconds
+    This function does NOT release thread quanta
+ 
+ @Input ui32Timeus - (us)
+
+ @Return IMG_VOID
+
+******************************************************************************/ 
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+
+/*!
+******************************************************************************
+
+ @Function OSSleepms
+ 
+ @Description 
+    This function implements a sleep of the specified milliseconds
+    This function may allow pre-emption if implemented
+ 
+ @Input ui32Timems - (ms)
+
+ @Return IMG_VOID
+
+******************************************************************************/ 
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems);
+
+IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID);
+IMG_UINT32 OSFuncHighResTimerGetus(IMG_HANDLE hTimer);
+IMG_VOID OSFuncHighResTimerDestroy(IMG_HANDLE hTimer);
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
+IMG_UINT32 OSPCIReadDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg);
+IMG_VOID OSPCIWriteDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg, IMG_UINT32 ui32Value);
+
+IMG_IMPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+IMG_IMPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
+
+#ifndef OSReadHWReg
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+#endif
+#ifndef OSWriteHWReg
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+#endif
+
+typedef IMG_VOID (*PFN_TIMER_FUNC)(IMG_VOID*);
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout);
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer);
+
+PVRSRV_ERROR OSGetSysMemSize(IMG_SIZE_T *puBytes);
+
+typedef enum _HOST_PCI_INIT_FLAGS_
+{
+	HOST_PCI_INIT_FLAG_BUS_MASTER	= 0x00000001,
+	HOST_PCI_INIT_FLAG_MSI		= 0x00000002,
+	HOST_PCI_INIT_FLAG_FORCE_I32 	= 0x7fffffff
+} HOST_PCI_INIT_FLAGS;
+
+struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_ *PVRSRV_PCI_DEV_HANDLE;
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ);
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+
+/******************************************************************************
+
+ @Function		OSPanic
+
+ @Description	Take action in response to an unrecoverable driver error
+
+ @Input    IMG_VOID
+
+ @Return   IMG_VOID
+
+******************************************************************************/
+IMG_VOID OSPanic(IMG_VOID);
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
+
+typedef enum _img_verify_test
+{
+	PVR_VERIFY_WRITE = 0,
+	PVR_VERIFY_READ
+} IMG_VERIFY_TEST;
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T uBytes);
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T uBytes);
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T uBytes);
+
+#if defined(__linux__) || defined(__QNXNTO__)
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr, 
+									IMG_SIZE_T uBytes, 
+									IMG_SYS_PHYADDR *psSysPAddr,
+									IMG_HANDLE *phOSWrapMem);
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSAcquirePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr, 
+												IMG_SIZE_T uBytes, 
+												IMG_SYS_PHYADDR *psSysPAddr,
+												IMG_HANDLE *phOSWrapMem)
+{
+	PVR_UNREFERENCED_PARAMETER(pvCPUVAddr);
+	PVR_UNREFERENCED_PARAMETER(uBytes);
+	PVR_UNREFERENCED_PARAMETER(psSysPAddr);
+	PVR_UNREFERENCED_PARAMETER(phOSWrapMem);
+	return PVRSRV_OK;	
+}
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleasePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+	PVR_UNREFERENCED_PARAMETER(hOSWrapMem);
+	return PVRSRV_OK;	
+}
+#endif
+									
+#if defined(__linux__) && defined(__KERNEL__)
+
+#define	OS_SUPPORTS_IN_LISR
+
+static inline IMG_BOOL OSInLISR(IMG_VOID unref__ *pvSysData)
+{
+	PVR_UNREFERENCED_PARAMETER(pvSysData);
+	return (in_irq()) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_VOID OSWriteMemoryBarrier(IMG_VOID)
+{
+	wmb();
+}
+
+static inline IMG_VOID OSMemoryBarrier(IMG_VOID)
+{
+	mb();
+}
+
+#else /* defined(__linux__) && defined(__KERNEL__) */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSWriteMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSWriteMemoryBarrier(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSMemoryBarrier(IMG_VOID) { }
+
+#endif /* defined(__linux__) && defined(__KERNEL__) */
+
+/* Atomic functions */
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount);
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount);
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount);
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount);
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount);
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32MSOffset);
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData);
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData);
+
+#if defined(__linux__)
+IMG_VOID OSReleaseBridgeLock(IMG_VOID);
+IMG_VOID OSReacquireBridgeLock(IMG_VOID);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleaseBridgeLock)
+#endif
+static INLINE IMG_VOID OSReleaseBridgeLock(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReacquireBridgeLock)
+#endif
+static INLINE IMG_VOID OSReacquireBridgeLock(IMG_VOID) { }
+
+#endif
+
+#if defined(__linux__)
+IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetCurrentProcessNameKM)
+#endif
+static INLINE IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size)
+{
+	PVR_UNREFERENCED_PARAMETER(pszName);
+	PVR_UNREFERENCED_PARAMETER(ui32Size);
+}
+
+#endif
+
+#if defined(__linux__) && defined(DEBUG)
+#define OSDumpStack dump_stack
+#else
+#define OSDumpStack()
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __OSFUNC_H__ */
+
+/******************************************************************************
+ End of file (osfunc.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/pvr/services4/srvkm/include/osperproc.h b/drivers/gpu/pvr/services4/srvkm/include/osperproc.h
new file mode 100644
index 0000000..0b962b4
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/osperproc.h
@@ -0,0 +1,94 @@
+/*************************************************************************/ /*!
+@Title          OS specific per process data interface
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	OS specific per process data interface
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __OSPERPROC_H__
+#define __OSPERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) || defined(__QNXNTO__)
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData);
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+#else	/* defined(__linux__) */
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+	PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataDeInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+	PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
+
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessSetHandleOptions)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+	PVR_UNREFERENCED_PARAMETER(psHandleBase);
+
+	return PVRSRV_OK;
+}
+#endif	/* defined(__linux__) */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __OSPERPROC_H__ */
+
+/******************************************************************************
+ End of file (osperproc.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/pdump_int.h b/drivers/gpu/pvr/services4/srvkm/include/pdump_int.h
new file mode 100644
index 0000000..a76fed0
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/pdump_int.h
@@ -0,0 +1,100 @@
+/*************************************************************************/ /*!
+@Title          Parameter dump internal common functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+#ifndef __PDUMP_INT_H__
+#define __PDUMP_INT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*
+ *	This file contains internal pdump utility functions which may be accessed
+ *	from OS-specific code. The header should not be included outside of srvkm
+ *	pdump files.
+ */
+
+#if !defined(_UITRON)
+/*
+ *	No dbgdriver on uitron, so ignore any common functions for communicating
+ *	with dbgdriver.
+ */
+#include "dbgdrvif.h"
+
+/* Callbacks which are registered with the debug driver. */
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID);
+
+#endif /* !defined(_UITRON) */
+
+typedef enum
+{
+	/* Continuous writes are always captured in the dbgdrv; the buffer will
+	 * expand if no client/sink process is running.
+	 */
+	PDUMP_WRITE_MODE_CONTINUOUS = 0,
+	/* Last frame capture */
+	PDUMP_WRITE_MODE_LASTFRAME,
+	/* Capture frame, binary data */
+	PDUMP_WRITE_MODE_BINCM,
+	/* Persistent capture, append data to init phase */
+	PDUMP_WRITE_MODE_PERSISTENT
+} PDUMP_DDWMODE;
+
+
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+IMG_UINT32 PDumpOSDebugDriverWrite(	PDBG_STREAM psStream,
+									PDUMP_DDWMODE eDbgDrvWriteMode,
+									IMG_UINT8 *pui8Data,
+									IMG_UINT32 ui32BCount,
+									IMG_UINT32 ui32Level,
+									IMG_UINT32 ui32DbgDrvFlags);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* __PDUMP_INT_H__ */
+
+/******************************************************************************
+ End of file (pdump_int.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/pvr/services4/srvkm/include/pdump_km.h b/drivers/gpu/pvr/services4/srvkm/include/pdump_km.h
new file mode 100644
index 0000000..4d62154
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/pdump_km.h
@@ -0,0 +1,446 @@
+/*************************************************************************/ /*!
+@Title          pdump functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Main APIs for pdump functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+
+/*
+ * Include the OS abstraction APIs
+ */
+#include "pdump_osfunc.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ *	Pull in pdump flags from services include
+ */
+#include "pdump.h"
+
+#define PDUMP_PD_UNIQUETAG			(IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG			(IMG_HANDLE)0
+
+/*
+ * PDump streams (common to all OSes)
+ */
+#define PDUMP_STREAM_PARAM2			0
+#define PDUMP_STREAM_SCRIPT2		1
+#define PDUMP_STREAM_DRIVERINFO		2
+#define PDUMP_NUM_STREAMS			3
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
+extern IMG_UINT32 g_ui32EveryLineCounter;
+#endif
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo)	(0)
+#endif
+
+IMG_BOOL _PDumpIsProcessActive(IMG_VOID);
+
+IMG_BOOL PDumpWillCapture(IMG_UINT32 ui32Flags);
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo)	(((BM_BUF *)(((PVRSRV_KERNEL_MEM_INFO *)(hMemInfo))->sMemBlk.hBuffer))->pMapping)
+
+	IMG_IMPORT PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+										  IMG_UINT32			ui32Offset,
+										  IMG_UINT32			ui32Value,
+										  IMG_UINT32			ui32Mask,
+										  PDUMP_POLL_OPERATOR	eOperator,
+										  IMG_UINT32			ui32Flags,
+										  IMG_HANDLE			hUniqueTag);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psProcData,
+									   IMG_PVOID			pvAltLinAddr,
+									   IMG_PVOID			pvLinAddr,
+									   PVRSRV_KERNEL_MEM_INFO	*psMemInfo,
+									   IMG_UINT32			ui32Offset,
+									   IMG_UINT32			ui32Bytes,
+									   IMG_UINT32			ui32Flags,
+									   IMG_HANDLE			hUniqueTag);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpMemKM(IMG_PVOID			pvAltLinAddr,
+									   PVRSRV_KERNEL_MEM_INFO	*psMemInfo,
+									   IMG_UINT32			ui32Offset,
+									   IMG_UINT32			ui32Bytes,
+									   IMG_UINT32			ui32Flags,
+									   IMG_HANDLE			hUniqueTag);
+	PVRSRV_ERROR PDumpMemPagesKM(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+								 IMG_DEV_PHYADDR		*pPages,
+								 IMG_UINT32			ui32NumPages,
+								 IMG_DEV_VIRTADDR	sDevAddr,
+								 IMG_UINT32			ui32Start,
+								 IMG_UINT32			ui32Length,
+								 IMG_UINT32			ui32Flags,
+								 IMG_HANDLE			hUniqueTag);
+
+	PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+									 IMG_HANDLE hOSMemHandle,
+							 		 IMG_CPU_VIRTADDR pvLinAddr,
+							 		 IMG_UINT32 ui32Bytes,
+							 		 IMG_UINT32 ui32Flags,
+							 		 IMG_BOOL bInitialisePages,
+							 		 IMG_HANDLE hUniqueTag1,
+							 		 IMG_HANDLE hUniqueTag2);
+							 
+	PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+									 IMG_HANDLE         hOSMemHandle,
+									 IMG_CPU_VIRTADDR	pvLinAddr,
+									 IMG_UINT32			ui32Bytes,
+									 IMG_UINT32			ui32Flags,
+									 IMG_BOOL			bInitialisePages,
+									 IMG_HANDLE			hUniqueTag1,
+									 IMG_HANDLE			hUniqueTag2);
+	IMG_VOID PDumpInitCommon(IMG_VOID);
+	IMG_VOID PDumpDeInitCommon(IMG_VOID);
+	IMG_VOID PDumpInit(IMG_VOID);
+	IMG_VOID PDumpDeInit(IMG_VOID);
+	IMG_BOOL PDumpIsSuspended(IMG_VOID);
+	PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID);
+	PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
+	IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
+	IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+	IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
+
+	PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+									 IMG_UINT32 ui32RegAddr,
+									 IMG_UINT32 ui32RegValue,
+									 IMG_UINT32 ui32Flags);
+	PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+										IMG_UINT32 ui32RegAddr,
+										IMG_UINT32 ui32RegValue,
+										IMG_UINT32 ui32Mask,
+										IMG_UINT32 ui32Flags,
+										PDUMP_POLL_OPERATOR	eOperator);
+	PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName,
+								IMG_UINT32 ui32RegAddr,
+								IMG_UINT32 ui32RegValue,
+								IMG_UINT32 ui32Mask,
+								PDUMP_POLL_OPERATOR	eOperator);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpBitmapKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+										  IMG_CHAR *pszFileName,
+										  IMG_UINT32 ui32FileOffset,
+										  IMG_UINT32 ui32Width,
+										  IMG_UINT32 ui32Height,
+										  IMG_UINT32 ui32StrideInBytes,
+										  IMG_DEV_VIRTADDR sDevBaseAddr,
+										  IMG_HANDLE hDevMemContext,
+										  IMG_UINT32 ui32Size,
+										  PDUMP_PIXEL_FORMAT ePixelFormat,
+										  PDUMP_MEM_FORMAT eMemFormat,
+										  IMG_UINT32 ui32PDumpFlags);
+	IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszPDumpRegName,
+										   IMG_CHAR *pszFileName,
+										   IMG_UINT32 ui32FileOffset,
+										   IMG_UINT32 ui32Address,
+										   IMG_UINT32 ui32Size,
+										   IMG_UINT32 ui32PDumpFlags);
+
+	PVRSRV_ERROR PDumpRegKM(IMG_CHAR* pszPDumpRegName,
+							IMG_UINT32 dwReg,
+							IMG_UINT32 dwData);
+
+	PVRSRV_ERROR PDumpComment(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+	PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32	ui32Flags,
+									   IMG_CHAR*	pszFormat,
+									   ...) IMG_FORMAT_PRINTF(2, 3);
+
+	PVRSRV_ERROR PDumpPDReg(PDUMP_MMU_ATTRIB *psMMUAttrib,
+							IMG_UINT32	ui32Reg,
+							IMG_UINT32	ui32dwData,
+							IMG_HANDLE	hUniqueTag);
+	PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+									 IMG_UINT32		ui32Reg,
+									 IMG_UINT32		ui32Data,
+									 IMG_UINT32		ui32Flags,
+									 IMG_HANDLE		hUniqueTag);
+
+	IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+	IMG_IMPORT IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID);
+
+	IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_IDENTIFIER	*psDevID,
+								  IMG_UINT32			ui32DevVAddr,
+								  IMG_PUINT32			pui32PhysPages,
+								  IMG_UINT32			ui32NumPages,
+								  IMG_HANDLE			hUniqueTag);
+	PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+									IMG_CHAR *pszMemSpace,
+									IMG_UINT32 *pui32MMUContextID,
+									IMG_UINT32 ui32MMUType,
+									IMG_HANDLE hUniqueTag1,
+									IMG_HANDLE hOSMemHandle,
+									IMG_VOID *pvPDCPUAddr);
+	PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+									IMG_CHAR *pszMemSpace,
+									IMG_UINT32 ui32MMUContextID,
+									IMG_UINT32 ui32MMUType);
+
+	PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+								   IMG_UINT32 ui32Offset,
+								   IMG_DEV_PHYADDR sPDDevPAddr,
+								   IMG_HANDLE hUniqueTag1,
+								   IMG_HANDLE hUniqueTag2);
+
+	IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame);
+
+	PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+							 	 IMG_CHAR			*pszFileName,
+								 IMG_UINT32			ui32FileOffset,
+								 IMG_DEV_VIRTADDR	sDevBaseAddr,
+								 IMG_UINT32 		ui32Size,
+								 IMG_UINT32 		ui32DataMaster,
+								 IMG_UINT32 		ui32PDumpFlags);
+
+	PVRSRV_ERROR PDumpTASignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+								   IMG_UINT32	ui32DumpFrameNum,
+								   IMG_UINT32	ui32TAKickCount,
+								   IMG_BOOL		bLastFrame,
+								   IMG_UINT32 *pui32Registers,
+								   IMG_UINT32 ui32NumRegisters);
+
+	PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+											IMG_UINT32 ui32DumpFrameNum,
+											IMG_BOOL bLastFrame,
+											IMG_UINT32 *pui32Registers,
+											IMG_UINT32 ui32NumRegisters);
+
+	PVRSRV_ERROR PDumpCounterRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+					IMG_UINT32 ui32DumpFrameNum,
+					IMG_BOOL		bLastFrame,
+					IMG_UINT32 *pui32Registers,
+					IMG_UINT32 ui32NumRegisters);
+
+	PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+								const IMG_UINT32 dwRegOffset,
+								IMG_UINT32	ui32Flags);
+
+	PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+										const IMG_UINT32 dwRegOffset,
+										IMG_BOOL bLastFrame);
+
+	PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+	PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+
+	PVRSRV_ERROR PDumpMallocPages(PVRSRV_DEVICE_IDENTIFIER	*psDevID,
+								  IMG_UINT32				ui32DevVAddr,
+								  IMG_CPU_VIRTADDR			pvLinAddr,
+								  IMG_HANDLE				hOSMemHandle,
+								  IMG_UINT32				ui32NumBytes,
+								  IMG_UINT32				ui32PageSize,
+								  IMG_HANDLE				hUniqueTag,
+								  IMG_UINT32				ui32Flags);
+	PVRSRV_ERROR PDumpMallocPageTable(PVRSRV_DEVICE_IDENTIFIER	*psDevId,
+									  IMG_HANDLE            hOSMemHandle,
+									  IMG_UINT32            ui32Offset,
+									  IMG_CPU_VIRTADDR		pvLinAddr,
+									  IMG_UINT32			ui32NumBytes,
+									  IMG_UINT32			ui32Flags,
+									  IMG_HANDLE			hUniqueTag);
+	PVRSRV_ERROR PDumpFreePages(struct _BM_HEAP_	*psBMHeap,
+							IMG_DEV_VIRTADDR	sDevVAddr,
+							IMG_UINT32			ui32NumBytes,
+							IMG_UINT32			ui32PageSize,
+							IMG_HANDLE      	hUniqueTag,
+							IMG_BOOL			bInterleaved,
+							IMG_BOOL			bSparse,
+							IMG_UINT32			ui32Flags);
+	PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+									IMG_HANDLE          hOSMemHandle,
+									IMG_CPU_VIRTADDR	pvLinAddr,
+									IMG_UINT32			ui32NumBytes,
+									IMG_UINT32			ui32Flags,
+									IMG_HANDLE			hUniqueTag);
+
+	IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+										IMG_CHAR			*pszFileName,
+										IMG_UINT32			ui32FileOffset,
+										IMG_DEV_VIRTADDR	sDevBaseAddr,
+										IMG_UINT32 			ui32Size,
+										IMG_UINT32			ui32MMUContextID,
+										IMG_UINT32 			ui32PDumpFlags);
+
+	PVRSRV_ERROR PDumpSignatureBuffer(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+									  IMG_CHAR			*pszFileName,
+									  IMG_CHAR			*pszBufferType,
+									  IMG_UINT32		ui32FileOffset,
+									  IMG_DEV_VIRTADDR	sDevBaseAddr,
+									  IMG_UINT32 		ui32Size,
+									  IMG_UINT32		ui32MMUContextID,
+									  IMG_UINT32 		ui32PDumpFlags);
+
+	PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO	psROffMemInfo,
+				  IMG_UINT32				ui32ROffOffset,
+				  IMG_UINT32				ui32WPosVal,
+				  IMG_UINT32				ui32PacketSize,
+				  IMG_UINT32				ui32BufferSize,
+				  IMG_UINT32				ui32Flags,
+				  IMG_HANDLE				hUniqueTag);
+
+	PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR		*pszPDumpRegName,
+								  IMG_UINT32	ui32RegOffset,
+								  IMG_UINT32	ui32WPosVal,
+								  IMG_UINT32	ui32PacketSize,
+								  IMG_UINT32	ui32BufferSize,
+								  IMG_UINT32	ui32Flags);
+
+	IMG_VOID PDumpVGXMemToFile(IMG_CHAR *pszFileName,
+							   IMG_UINT32 ui32FileOffset, 
+							   PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+							   IMG_UINT32 uiAddr, 
+							   IMG_UINT32 ui32Size,
+							   IMG_UINT32 ui32PDumpFlags,
+							   IMG_HANDLE hUniqueTag);
+
+	IMG_VOID PDumpSuspendKM(IMG_VOID);
+	IMG_VOID PDumpResumeKM(IMG_VOID);
+
+	/* New pdump common functions */
+	PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+							         IMG_CHAR *pszFileName,
+									 IMG_UINT32 ui32FileOffset, 
+									 PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+									 IMG_UINT32 uiAddr, 
+									 IMG_UINT32 ui32Size,
+									 IMG_UINT32 ui32PDumpFlags,
+									 IMG_HANDLE hUniqueTag);
+
+	#define PDUMPMEMPOL				PDumpMemPolKM
+	#define PDUMPMEM				PDumpMemKM
+	#define PDUMPMEMPTENTRIES		PDumpMemPTEntriesKM
+	#define PDUMPPDENTRIES			PDumpMemPDEntriesKM
+	#define PDUMPMEMUM				PDumpMemUM
+	#define PDUMPINIT				PDumpInitCommon
+	#define PDUMPDEINIT				PDumpDeInitCommon
+	#define PDUMPISLASTFRAME		PDumpIsLastCaptureFrameKM
+	#define PDUMPTESTFRAME			PDumpIsCaptureFrameKM
+	#define PDUMPTESTNEXTFRAME		PDumpTestNextFrame
+	#define PDUMPREGWITHFLAGS		PDumpRegWithFlagsKM
+	#define PDUMPREG				PDumpRegKM
+	#define PDUMPCOMMENT			PDumpComment
+	#define PDUMPCOMMENTWITHFLAGS	PDumpCommentWithFlags
+	#define PDUMPREGPOL				PDumpRegPolKM
+	#define PDUMPREGPOLWITHFLAGS	PDumpRegPolWithFlagsKM
+	#define PDUMPMALLOCPAGES		PDumpMallocPages
+	#define PDUMPMALLOCPAGETABLE	PDumpMallocPageTable
+	#define PDUMPSETMMUCONTEXT		PDumpSetMMUContext
+	#define PDUMPCLEARMMUCONTEXT	PDumpClearMMUContext
+    #define PDUMPPDDEVPADDR         PDumpPDDevPAddrKM
+	#define PDUMPFREEPAGES			PDumpFreePages
+	#define PDUMPFREEPAGETABLE		PDumpFreePageTable
+	#define PDUMPPDREG				PDumpPDReg
+	#define PDUMPPDREGWITHFLAGS		PDumpPDRegWithFlags
+	#define PDUMPCBP				PDumpCBP
+	#define PDUMPREGBASEDCBP		PDumpRegBasedCBP
+	#define PDUMPMALLOCPAGESPHYS	PDumpMallocPagesPhys
+	#define PDUMPENDINITPHASE		PDumpStopInitPhaseKM
+	#define PDUMPBITMAPKM			PDumpBitmapKM
+	#define PDUMPDRIVERINFO			PDumpDriverInfoKM
+	#define PDUMPIDLWITHFLAGS		PDumpIDLWithFlags
+	#define PDUMPIDL				PDumpIDL
+	#define PDUMPSUSPEND			PDumpSuspendKM
+	#define PDUMPRESUME				PDumpResumeKM
+
+#else
+#if defined LINUX || defined (__QNXNTO__) || defined GCC_IA32 || defined GCC_ARM
+			#define PDUMPMEMPOL(args...)
+			#define PDUMPMEM(args...)
+			#define PDUMPMEMPTENTRIES(args...)
+			#define PDUMPPDENTRIES(args...)
+			#define PDUMPMEMUM(args...)
+			#define PDUMPINIT(args...)
+			#define PDUMPDEINIT(args...)
+			#define PDUMPISLASTFRAME(args...)
+			#define PDUMPTESTFRAME(args...)
+			#define PDUMPTESTNEXTFRAME(args...)
+			#define PDUMPREGWITHFLAGS(args...)
+			#define PDUMPREG(args...)
+			#define PDUMPCOMMENT(args...)
+			#define PDUMPREGPOL(args...)
+			#define PDUMPREGPOLWITHFLAGS(args...)
+			#define PDUMPMALLOCPAGES(args...)
+			#define PDUMPMALLOCPAGETABLE(args...)
+			#define PDUMPSETMMUCONTEXT(args...)
+			#define PDUMPCLEARMMUCONTEXT(args...)
+            #define PDUMPPDDEVPADDR(args...)
+			#define PDUMPFREEPAGES(args...)
+			#define PDUMPFREEPAGETABLE(args...)
+			#define PDUMPPDREG(args...)
+			#define PDUMPPDREGWITHFLAGS(args...)
+			#define PDUMPSYNC(args...)
+			#define PDUMPCOPYTOMEM(args...)
+			#define PDUMPWRITE(args...)
+			#define PDUMPCBP(args...)
+			#define PDUMPREGBASEDCBP(args...)
+			#define PDUMPCOMMENTWITHFLAGS(args...)
+			#define PDUMPMALLOCPAGESPHYS(args...)
+			#define PDUMPENDINITPHASE(args...)
+			#define PDUMPMSVDXREG(args...)
+			#define PDUMPMSVDXREGWRITE(args...)
+			#define PDUMPMSVDXREGREAD(args...)
+			#define PDUMPMSVDXPOLEQ(args...)
+			#define PDUMPMSVDXPOL(args...)
+			#define PDUMPBITMAPKM(args...)
+			#define PDUMPDRIVERINFO(args...)
+			#define PDUMPIDLWITHFLAGS(args...)
+			#define PDUMPIDL(args...)
+			#define PDUMPSUSPEND(args...)
+			#define PDUMPRESUME(args...)
+			#define PDUMPMSVDXWRITEREF(args...)
+		#else
+			#error Compiler not specified
+		#endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* _PDUMP_KM_H_ */
+
+/******************************************************************************
+ End of file (pdump_km.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/pdump_osfunc.h b/drivers/gpu/pvr/services4/srvkm/include/pdump_osfunc.h
new file mode 100644
index 0000000..9fc1fd8
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/pdump_osfunc.h
@@ -0,0 +1,385 @@
+/*************************************************************************/ /*!
+@Title          OS-independent interface to helper functions for pdump
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* 
+ * Some OSes (WinXP,CE) allocate the string on the stack, but some
+ * (Linux,Symbian) use a global variable/lock instead.
+ * Would be good to use the same across all OSes.
+ *
+ * A handle is returned which represents IMG_CHAR* type on all OSes except
+ * Symbian when it represents PDumpState* type.
+ *
+ * The allocated buffer length is also returned on OSes where it's
+ * supported (e.g. Linux).
+ */
+#define MAX_PDUMP_STRING_LENGTH (256)
+
+
+#if defined(__QNXNTO__)
+
+#define PDUMP_GET_SCRIPT_STRING()	\
+	IMG_CHAR pszScript[MAX_PDUMP_STRING_LENGTH];		\
+	IMG_UINT32	ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;	\
+	IMG_HANDLE	hScript = (IMG_HANDLE)pszScript;
+
+#define PDUMP_GET_MSG_STRING()		\
+	IMG_CHAR pszMsg[MAX_PDUMP_STRING_LENGTH];			\
+	IMG_UINT32	ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+
+#define PDUMP_GET_FILE_STRING()		\
+	IMG_CHAR	pszFileName[MAX_PDUMP_STRING_LENGTH];	\
+	IMG_UINT32	ui32MaxLen = MAX_PDUMP_STRING_LENGTH-1;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING()		\
+	IMG_CHAR 	pszScript[MAX_PDUMP_STRING_LENGTH];		\
+	IMG_CHAR	pszFileName[MAX_PDUMP_STRING_LENGTH];	\
+	IMG_UINT32	ui32MaxLenScript = MAX_PDUMP_STRING_LENGTH-1;	\
+	IMG_UINT32	ui32MaxLenFileName = MAX_PDUMP_STRING_LENGTH-1;	\
+	IMG_HANDLE	hScript = (IMG_HANDLE)pszScript;
+
+#define PDUMP_LOCK(args...)
+#define PDUMP_UNLOCK(args...)
+#define PDUMP_LOCK_MSG(args...)
+#define PDUMP_UNLOCK_MSG(args...)
+
+#else  /* __QNXNTO__ */
+
+
+	/*
+	 * Linux
+	 */
+#define PDUMP_GET_SCRIPT_STRING()				\
+	IMG_HANDLE hScript;							\
+	IMG_UINT32	ui32MaxLen;						\
+	PVRSRV_ERROR eError;						\
+	eError = PDumpOSGetScriptString(&hScript, &ui32MaxLen);\
+	if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_MSG_STRING()					\
+	IMG_CHAR *pszMsg;							\
+	IMG_UINT32	ui32MaxLen;						\
+	PVRSRV_ERROR eError;						\
+	eError = PDumpOSGetMessageString(&pszMsg, &ui32MaxLen);\
+	if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_FILE_STRING()				\
+	IMG_CHAR *pszFileName;					\
+	IMG_UINT32	ui32MaxLen;					\
+	PVRSRV_ERROR eError;					\
+	eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLen);\
+	if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING()		\
+	IMG_HANDLE hScript;							\
+	IMG_CHAR *pszFileName;						\
+	IMG_UINT32	ui32MaxLenScript;				\
+	IMG_UINT32	ui32MaxLenFileName;				\
+	PVRSRV_ERROR eError;						\
+	eError = PDumpOSGetScriptString(&hScript, &ui32MaxLenScript);\
+	if(eError != PVRSRV_OK) return eError;		\
+	eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
+	if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_LOCK()		\
+	PDumpOSLock(__LINE__);
+
+#define PDUMP_UNLOCK()		\
+	PDumpOSUnlock(__LINE__);
+
+#define PDUMP_LOCK_MSG()		\
+	PDumpOSLockMessageBuffer();
+
+#define PDUMP_UNLOCK_MSG()		\
+	PDumpOSUnlockMessageBuffer();
+
+	/*!
+	 * @name	PDumpOSLock
+	 * @brief	Lock the PDump streams
+	 * @return	error none
+	 */
+	IMG_VOID PDumpOSLock(IMG_UINT32 ui32Line);
+
+	/*!
+	 * @name	PDumpOSUnlock
+	 * @brief	Lock the PDump streams
+	 * @return	error none
+	 */
+	IMG_VOID PDumpOSUnlock(IMG_UINT32 ui32Line);
+
+	/*!
+	 * @name	PDumpOSLockMessageBuffer
+	 * @brief	Lock the PDump message buffer
+	 * @return	error none
+	 */
+	IMG_VOID PDumpOSLockMessageBuffer(IMG_VOID);
+
+	/*!
+	 * @name	PDumpOSUnlockMessageBuffer
+	 * @brief	Lock the PDump message buffer
+	 * @return	error none
+	 */
+	IMG_VOID PDumpOSUnlockMessageBuffer(IMG_VOID);
+
+#endif /* __QNXNTO__ */
+
+	/*!
+	 * @name	PDumpOSGetScriptString
+	 * @brief	Get the "script" buffer
+	 * @param	phScript - buffer handle for pdump script
+	 * @param	pui32MaxLen - max length of the script buffer
+	 *              FIXME: the max length should be internal to the OS-specific code
+	 * @return	error (always PVRSRV_OK on some OSes)
+	 */
+	PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
+
+	/*!
+	 * @name	PDumpOSGetMessageString
+	 * @brief	Get the "message" buffer
+	 * @param	pszMsg - buffer pointer for pdump messages
+	 * @param	pui32MaxLen - max length of the message buffer
+	 *              FIXME: the max length should be internal to the OS-specific code
+	 * @return	error (always PVRSRV_OK on some OSes)
+	 */
+	PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
+
+	/*!
+	 * @name	PDumpOSGetFilenameString
+	 * @brief	Get the "filename" buffer
+	 * @param	ppszFile - buffer pointer for filename
+	 * @param	pui32MaxLen - max length of the filename buffer
+	 *              FIXME: the max length should be internal to the OS-specific code
+	 * @return	error (always PVRSRV_OK on some OSes)
+	 */
+	PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+
+
+/*
+ * Define macro for processing variable args list in OS-independent
+ * manner. See e.g. PDumpComment().
+ */
+
+#define PDUMP_va_list	va_list
+#define PDUMP_va_start	va_start
+#define PDUMP_va_end	va_end
+
+
+
+/*!
+ * @name	PDumpOSGetStream
+ * @brief	Get a handle to the labelled stream (cast the handle to PDBG_STREAM to use it)
+ * @param	ePDumpStream - stream label
+ */
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+
+/*!
+ * @name	PDumpOSGetStreamOffset
+ * @brief	Return current offset within the labelled stream
+ * @param	ePDumpStream - stream label
+ */
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+
+/*!
+ * @name	PDumpOSGetParamFileNum
+ * @brief	Return file number of the 'script' stream, in the case that the file was split
+ * @param	ePDumpStream - stream label
+ */
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+
+/*!
+ * @name	PDumpOSCheckForSplitting
+ * @brief	Check if the requested pdump params are too large for a single file
+ * @param	hStream - pdump stream
+ * @param	ui32Size - size of params to dump (bytes)
+ * @param	ui32Flags - pdump flags
+ */
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+
+/*!
+ * @name	PDumpOSIsSuspended
+ * @brief	Is the pdump stream busy?
+ * @return	IMG_BOOL
+ */
+IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+
+/*!
+ * @name	PDumpOSIsSuspended
+ * @brief	Is the pdump jump table initialised?
+ * @return	IMG_BOOL
+ */
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+
+/*!
+ * @name	PDumpOSWriteString
+ * @brief	General function for writing to pdump stream.
+ * 			Usually more convenient to use PDumpOSWriteString2 below.
+ * @param	hDbgStream - pdump stream handle
+ * @param	psui8Data - data to write
+ * @param	ui32Size - size of write
+ * @param	ui32Flags - pdump flags
+ * @return	error
+ */
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
+		IMG_UINT8 *psui8Data,
+		IMG_UINT32 ui32Size,
+		IMG_UINT32 ui32Flags);
+
+/*!
+ * @name	PDumpOSWriteString2
+ * @brief	Write a string to the "script" output stream
+ * @param	pszScript - buffer to write (ptr to state structure on Symbian)
+ * @param	ui32Flags - pdump flags
+ * @return	error
+ */
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE	hScript, IMG_UINT32 ui32Flags);
+
+/*!
+ * @name	PDumpOSBufprintf
+ * @brief	Printf to OS-specific pdump state buffer
+ * @param	hBuf - buffer handle to write into (ptr to state structure on Symbian)
+ * @param	ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param	pszFormat - format string
+ */
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+/*!
+ * @name	PDumpOSDebugPrintf
+ * @brief	Debug message during pdumping
+ * @param	pszFormat - format string
+ */
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+/*
+ * Write into a IMG_CHAR* on all OSes. Can be allocated on the stack or heap.
+ */
+/*!
+ * @name	PDumpOSSprintf
+ * @brief	Printf to IMG char array
+ * @param	pszComment - char array to print into
+ * @param	pszFormat - format string
+ */
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+/*!
+ * @name	PDumpOSVSprintf
+ * @brief	Printf to IMG string using variable args (see stdarg.h). This is necessary
+ * 			because the ... notation does not support nested function calls.
+ * @param	pszMsg - char array to print into
+ * @param	ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param	pszFormat - format string
+ * @param	vaArgs - variable args structure (from stdarg.h)
+ */
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+
+/*!
+ * @name	PDumpOSBuflen
+ * @param	hBuffer - handle to buffer (ptr to state structure on Symbian)
+ * @param	ui32BuffeRSizeMax - max size of buffer (chars)
+ * @return	length of buffer, will always be <= ui32BufferSizeMax
+ */
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+/*!
+ * @name	PDumpOSVerifyLineEnding
+ * @brief	Put \r\n sequence at the end if it isn't already there
+ * @param	hBuffer - handle to buffer
+ * @param	ui32BufferSizeMax - max size of buffer (chars)
+ */
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+/*!
+ * @name	PDumpOSCPUVAddrToDevPAddr
+ * @brief	OS function to convert CPU virtual to device physical for dumping pages
+ * @param	hOSMemHandle	mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param	ui32Offset		dword offset into allocation (for use with mem handle, e.g. linux)
+ * @param	pui8LinAddr		CPU linear addr (usually a kernel virtual address)
+ * @param	ui32PageSize	page size, used for assertion check
+ * @return	psDevPAddr		device physical addr
+ */
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+        IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_UINT8 *pui8LinAddr,
+		IMG_UINT32 ui32PageSize,
+		IMG_DEV_PHYADDR *psDevPAddr);
+
+/*!
+ * @name	PDumpOSCPUVAddrToPhysPages
+ * @brief	OS function to convert CPU virtual to backing physical pages
+ * @param	hOSMemHandle	mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param	ui32Offset		offset within mem allocation block
+ * @param	pui8LinAddr		CPU linear addr
+ * @param	uiDataPageMask	mask for data page (= data page size -1)
+ * @return	pui32PageOffset	CPU page offset (same as device page offset if page sizes equal)
+ */
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+		IMG_UINT32 ui32Offset,
+		IMG_PUINT8 pui8LinAddr,
+		IMG_UINTPTR_T uiDataPageMask,
+		IMG_UINT32 *pui32PageOffset);
+
+/*!
+ * @name	PDumpOSReleaseExecution
+ * @brief	OS function to switch to another process, to clear pdump buffers
+ */
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID);
+
+/*!
+ * @name	PDumpOSIsCaptureFrameKM
+ * @brief	Is the current frame a capture frame?
+ */
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID);
+
+/*!
+ * @name	PDumpOSSetFrameKM
+ * @brief	Set frame counter
+ */
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame);
+
+#if defined (__cplusplus)
+}
+#endif
diff --git a/drivers/gpu/pvr/services4/srvkm/include/perfkm.h b/drivers/gpu/pvr/services4/srvkm/include/perfkm.h
new file mode 100644
index 0000000..458a29b
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/perfkm.h
@@ -0,0 +1,53 @@
+/*************************************************************************/ /*!
+@Title          Perf initialisation
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef _PERFKM_H_
+#define _PERFKM_H_
+
+#include "img_types.h"
+
+#define PERFINIT()
+#define PERFDEINIT()
+
+#endif /* _PERFKM_H_ */
+
+/******************************************************************************
+  End of file (perfkm.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/perproc.h b/drivers/gpu/pvr/services4/srvkm/include/perproc.h
new file mode 100644
index 0000000..124f2f2
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/perproc.h
@@ -0,0 +1,141 @@
+/*************************************************************************/ /*!
+@Title          Handle Manager API
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	Perprocess data
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef __PERPROC_H__
+#define __PERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+typedef struct _PVRSRV_PER_PROCESS_DATA_
+{
+	IMG_UINT32		ui32PID;
+	IMG_HANDLE		hBlockAlloc;
+	PRESMAN_CONTEXT 	hResManContext;
+	IMG_HANDLE		hPerProcData;
+	PVRSRV_HANDLE_BASE 	*psHandleBase;
+#if defined (PVR_SECURE_HANDLES)
+	/* Handles are being allocated in batches */
+	IMG_BOOL		bHandlesBatched;
+#endif  /* PVR_SECURE_HANDLES */
+	IMG_UINT32		ui32RefCount;
+
+	/* True if the process is the initialisation server. */
+	IMG_BOOL		bInitProcess;
+#if defined(PDUMP)
+	/* True if pdump data from the process is 'persistent' */
+	IMG_BOOL		bPDumpPersistent;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+	/* True if this process is marked for pdumping. This flag is
+	 * significant in a multi-app environment.
+	 */
+	IMG_BOOL		bPDumpActive;
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+#endif
+	/*
+	 * OS specific data can be stored via this handle.
+	 * See osperproc.h for a generic mechanism for initialising
+	 * this field.
+	 */
+	IMG_HANDLE		hOsPrivateData;
+} PVRSRV_PER_PROCESS_DATA;
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32	ui32PID, IMG_UINT32 ui32Flags);
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32	ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID);
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessData)
+#endif
+static INLINE
+PVRSRV_PER_PROCESS_DATA *PVRSRVFindPerProcessData(IMG_VOID)
+{
+	return PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVProcessPrivateData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+	return (psPerProc != IMG_NULL) ? psPerProc->hOsPrivateData : IMG_NULL;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVPerProcessPrivateData(IMG_UINT32 ui32PID)
+{
+	return PVRSRVProcessPrivateData(PVRSRVPerProcessData(ui32PID));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVFindPerProcessPrivateData(IMG_VOID)
+{
+	return PVRSRVProcessPrivateData(PVRSRVFindPerProcessData());
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __PERPROC_H__ */
+
+/******************************************************************************
+ End of file (perproc.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/power.h b/drivers/gpu/pvr/services4/srvkm/include/power.h
new file mode 100644
index 0000000..0abaf75
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/power.h
@@ -0,0 +1,140 @@
+/*************************************************************************/ /*!
+@Title          Power Management Functions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Main APIs for power management functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#ifndef POWER_H
+#define POWER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/*!
+ *****************************************************************************
+ *	Power management
+ *****************************************************************************/
+ 
+typedef struct _PVRSRV_POWER_DEV_TAG_
+{
+	PFN_PRE_POWER					pfnPrePower;
+	PFN_POST_POWER					pfnPostPower;
+	PFN_PRE_CLOCKSPEED_CHANGE		pfnPreClockSpeedChange;
+	PFN_POST_CLOCKSPEED_CHANGE		pfnPostClockSpeedChange;
+	IMG_HANDLE						hDevCookie;
+	IMG_UINT32						ui32DeviceIndex;
+	PVRSRV_DEV_POWER_STATE 			eDefaultPowerState;
+	PVRSRV_DEV_POWER_STATE 			eCurrentPowerState;
+	struct _PVRSRV_POWER_DEV_TAG_	*psNext;
+	struct _PVRSRV_POWER_DEV_TAG_	**ppsThis;
+
+} PVRSRV_POWER_DEV;
+
+typedef enum _PVRSRV_INIT_SERVER_STATE_
+{
+	PVRSRV_INIT_SERVER_Unspecified		= -1,	
+	PVRSRV_INIT_SERVER_RUNNING			= 0,	
+	PVRSRV_INIT_SERVER_RAN				= 1,	
+	PVRSRV_INIT_SERVER_SUCCESSFUL		= 2,	
+	PVRSRV_INIT_SERVER_NUM				= 3,	
+	PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
+
+IMG_IMPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE	eInitServerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE	eInitServerState, IMG_BOOL bState);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32	ui32CallerID,
+							 IMG_BOOL	bSystemPowerEvent);
+IMG_IMPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32	ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32				ui32DeviceIndex,
+										 PVRSRV_DEV_POWER_STATE	eNewPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32					ui32DeviceIndex,
+									   PFN_PRE_POWER				pfnPrePower,
+									   PFN_POST_POWER				pfnPostPower,
+									   PFN_PRE_CLOCKSPEED_CHANGE	pfnPreClockSpeedChange,
+									   PFN_POST_CLOCKSPEED_CHANGE	pfnPostClockSpeedChange,
+									   IMG_HANDLE					hDevCookie,
+									   PVRSRV_DEV_POWER_STATE		eCurrentPowerState,
+									   PVRSRV_DEV_POWER_STATE		eDefaultPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+											 IMG_BOOL	bIdleDevice,
+											 IMG_VOID	*pvInfo);
+
+IMG_IMPORT
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32	ui32DeviceIndex,
+										  IMG_BOOL		bIdleDevice,
+										  IMG_VOID		*pvInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif /* POWER_H */
+
+/******************************************************************************
+ End of file (power.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/queue.h b/drivers/gpu/pvr/services4/srvkm/include/queue.h
new file mode 100644
index 0000000..2af7a34
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/queue.h
@@ -0,0 +1,154 @@
+/*************************************************************************/ /*!
+@Title          Command Queue API
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Internal structures and definitions for command queues
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * Macro to Read Offset in given command queue
+ */
+#define UPDATE_QUEUE_ROFF(psQueue, uSize)						\
+	(psQueue)->uReadOffset = ((psQueue)->uReadOffset + (uSize))	\
+	& ((psQueue)->uQueueSize - 1);
+
+/*!
+	generic cmd complete structure.
+	This structure represents the storage required between starting and finishing
+	a given cmd and is required to hold the generic sync object update data.
+	note: for any given system we know what command types we support and
+	therefore how much storage is required for any number of commands in progress
+ */
+ typedef struct _COMMAND_COMPLETE_DATA_
+ {
+	IMG_BOOL			bInUse;
+	/* <arg(s) to PVRSRVProcessQueues>;	*/	/*!< TBD */
+	IMG_UINT32			ui32DstSyncCount;	/*!< number of dst sync objects */
+	IMG_UINT32			ui32SrcSyncCount;	/*!< number of src sync objects */
+	PVRSRV_SYNC_OBJECT	*psDstSync;			/*!< dst sync ptr list, 
+                                        	allocated on back of this structure */
+	PVRSRV_SYNC_OBJECT	*psSrcSync;			/*!< src sync ptr list, 
+                                       		allocated on back of this structure */
+	IMG_UINT32			ui32AllocSize;		/*!< allocated size*/
+	PFN_QUEUE_COMMAND_COMPLETE	pfnCommandComplete;	/*!< Command complete callback */
+	IMG_HANDLE					hCallbackData;		/*!< Command complete callback data */
+
+#if defined(PVR_ANDROID_NATIVE_WINDOW_HAS_SYNC) || defined(PVR_ANDROID_NATIVE_WINDOW_HAS_FENCE)
+	IMG_VOID			*pvCleanupFence;	/*!< Sync fence to 'put' after timeline inc() */
+	IMG_VOID			*pvTimeline;		/*!< Android sync timeline to inc() */
+#endif
+ }COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
+
+#if !defined(USE_CODE)
+IMG_VOID QueueDumpDebugInfo(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVProcessQueues (IMG_BOOL		bFlush);
+
+#if defined(__linux__) && defined(__KERNEL__) 
+#include <linux/types.h>
+#include <linux/seq_file.h>
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off);
+void ProcSeqShowQueue(struct seq_file *sfile,void* el);
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T uQueueSize,
+													 PVRSRV_QUEUE_INFO **ppsQueueInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO	*psQueue,
+												PVRSRV_COMMAND		**ppsCommand,
+												IMG_UINT32			ui32DevIndex,
+												IMG_UINT16			CommandType,
+												IMG_UINT32			ui32DstSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsDstSync[],
+												IMG_UINT32			ui32SrcSyncCount,
+												PVRSRV_KERNEL_SYNC_INFO	*apsSrcSync[],
+												IMG_SIZE_T			ui32DataByteSize,
+												PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+												IMG_HANDLE			hCallbackData,
+												IMG_HANDLE			*phFence);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+												IMG_SIZE_T uParamSize,
+												IMG_VOID **ppvSpace);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+												PVRSRV_COMMAND *psCommand);
+
+IMG_IMPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, IMG_BOOL bScheduleMISR);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32		ui32DevIndex,
+										 PFN_CMD_PROC	*ppfnCmdProcList,
+										 IMG_UINT32		ui32MaxSyncsPerCmd[][2],
+										 IMG_UINT32		ui32CmdCount);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32	ui32DevIndex,
+									   IMG_UINT32	ui32CmdCount);
+
+#endif /* !defined(USE_CODE) */
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* defined(SUPPORT_PVRSRV_DEVICE_CLASS) */
+
+#endif /* QUEUE_H */
+
+/******************************************************************************
+ End of file (queue.h)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/ra.h b/drivers/gpu/pvr/services4/srvkm/include/ra.h
new file mode 100644
index 0000000..aaeb345
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/ra.h
@@ -0,0 +1,290 @@
+/*************************************************************************/ /*!
+@Title          Resource Allocator API
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _RA_H_
+#define _RA_H_
+
+#include "img_types.h"
+#include "hash.h"
+#include "osfunc.h"
+
+/** Resource arena.
+ *  struct _RA_ARENA_ deliberately opaque
+ */
+typedef struct _RA_ARENA_ RA_ARENA;			//PRQA S 3313
+typedef struct _BM_MAPPING_ BM_MAPPING;
+
+
+
+/** Enable support for arena statistics. */
+#define RA_STATS 
+
+
+/** Resource arena statistics. */
+struct _RA_STATISTICS_
+{
+    /** total number of segments add to the arena */
+    IMG_SIZE_T uSpanCount;
+
+    /** number of current live segments within the arena */
+    IMG_SIZE_T uLiveSegmentCount;
+
+    /** number of current free segments within the arena */
+    IMG_SIZE_T uFreeSegmentCount;
+
+    /** total number of resource within the arena */
+    IMG_SIZE_T uTotalResourceCount;
+    
+    /** number of free resource within the arena */
+    IMG_SIZE_T uFreeResourceCount;
+
+    /** total number of resources allocated from the arena */
+    IMG_SIZE_T uCumulativeAllocs;
+
+    /** total number of resources returned to the arena */
+    IMG_SIZE_T uCumulativeFrees;
+
+    /** total number of spans allocated by the callback mechanism */
+    IMG_SIZE_T uImportCount;
+
+    /** total number of spans deallocated by the callback mechanism */
+    IMG_SIZE_T uExportCount;
+};
+typedef struct _RA_STATISTICS_ RA_STATISTICS;
+
+struct _RA_SEGMENT_DETAILS_
+{
+	IMG_SIZE_T      uiSize;
+	IMG_CPU_PHYADDR sCpuPhyAddr;
+	IMG_HANDLE      hSegment;
+};
+typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+
+/**
+ *  @Function   RA_Create
+ *
+ *  @Description
+ *
+ *  To create a resource arena.
+ *
+ *  @Input name - the name of the arena for diagnostic purposes.
+ *  @Input base - the base of an initial resource span or 0.
+ *  @Input uSize - the size of an initial resource span or 0.
+ *  @Input pRef - the reference to return for the initial resource or 0.
+ *  @Input uQuantum - the arena allocation quantum.
+ *  @Input alloc - a resource allocation callback or 0.
+ *  @Input free - a resource de-allocation callback or 0.
+ *  @Input import_handle - handle passed to alloc and free or 0.
+ *  @Return arena handle, or IMG_NULL.
+ */
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+           IMG_UINTPTR_T base,
+           IMG_SIZE_T uSize,
+           BM_MAPPING *psMapping,
+           IMG_SIZE_T uQuantum, 
+           IMG_BOOL (*imp_alloc)(IMG_VOID *_h,
+                                IMG_SIZE_T uSize,
+                                IMG_SIZE_T *pActualSize,
+                                BM_MAPPING **ppsMapping,
+                                IMG_UINT32 uFlags,
+								IMG_PVOID pvPrivData,
+								IMG_UINT32 ui32PrivDataLength,
+                                IMG_UINTPTR_T *pBase),
+           IMG_VOID (*imp_free) (IMG_VOID *,
+                                IMG_UINTPTR_T,
+                                BM_MAPPING *),
+           IMG_VOID (*backingstore_free) (IMG_VOID *,
+                                          IMG_SIZE_T,
+                                          IMG_SIZE_T,
+                                          IMG_HANDLE),
+           IMG_VOID *import_handle);
+
+/**
+ *  @Function   RA_Delete
+ *
+ *  @Description
+ *
+ *  To delete a resource arena. All resources allocated from the arena
+ *  must be freed before deleting the arena.
+ *                  
+ *  @Input  pArena - the arena to delete.
+ *  @Return None
+ */
+IMG_VOID
+RA_Delete (RA_ARENA *pArena);
+
+/**
+ *  @Function   RA_TestDelete
+ *
+ *  @Description
+ *
+ *  To test whether it is safe to delete a resource arena. If any allocations
+ *	have not been freed, the RA must not be deleted.
+ *                  
+ *  @Input  pArena - the arena to test.
+ *  @Return IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete.
+ */
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena);
+
+/**
+ *  @Function   RA_Add
+ *
+ *  @Description
+ *
+ *  To add a resource span to an arena. The span must not overlap with
+ *  any span previously added to the arena.
+ *
+ *  @Input pArena - the arena to add a span into.
+ *  @Input base - the base of the span.
+ *  @Input uSize - the extent of the span.
+ *  @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+
+/**
+ *  @Function   RA_Alloc
+ *
+ *  @Description
+ *
+ *  To allocate resource from an arena.
+ *
+ *  @Input  pArena - the arena
+ *  @Input  uRequestSize - the size of resource segment requested.
+ *  @Output pActualSize - the actual_size of resource segment allocated,
+ *          typcially rounded up by quantum.
+ *  @Output ppsMapping - the user reference associated with allocated
+ *          resource span.
+ *  @Input  uFlags - flags influencing allocation policy.
+ *  @Input  uAlignment - the alignment constraint required for the
+ *          allocated segment, use 0 if alignment not required.
+ *	@Input  uAlignmentOffset - the required alignment offset
+ *  @Input  pvPrivData - private data passed to OS allocator
+ *  @Input  ui32PrivData - length of private data
+ *
+ *  @Output pBase - allocated base resource
+ *  @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena, 
+          IMG_SIZE_T uSize,
+          IMG_SIZE_T *pActualSize,
+          BM_MAPPING **ppsMapping, 
+          IMG_UINT32 uFlags,
+          IMG_UINT32 uAlignment,
+		  IMG_UINT32 uAlignmentOffset,
+		  IMG_PVOID pvPrivData,
+		  IMG_UINT32 ui32PrivDataLength,
+          IMG_UINTPTR_T *pBase);
+
+/**
+ *  @Function   RA_Free
+ *
+ *  @Description    To free a resource segment.
+ *  
+ *  @Input  pArena - the arena the segment was originally allocated from.
+ *  @Input  base - the base of the resource span to free.
+ *	@Input	bFreeBackingStore - Should backing store memory be freed?
+ *
+ *  @Return None
+ */
+IMG_VOID 
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
+
+
+#ifdef RA_STATS
+
+#define CHECK_SPACE(total)					\
+{											\
+	if((total)<100) 							\
+		return PVRSRV_ERROR_INVALID_PARAMS;	\
+}
+
+#define UPDATE_SPACE(str, count, total)		\
+{											\
+	if((count) == -1)					 		\
+		return PVRSRV_ERROR_INVALID_PARAMS;	\
+	else									\
+	{										\
+		(str) += (count);						\
+		(total) -= (count);						\
+	}										\
+}
+
+
+/**
+ * @Function    RA_GetNextLiveSegment
+ * 
+ * @Description Returns details of the next live resource segments
+ * 
+ * @Input       pArena - the arena the segment was originally allocated from.
+ * @Output      psSegDetails - rtn details of segments
+ * 
+ * @Return      IMG_TRUE if operation succeeded
+ */
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+
+
+/**
+ *  @Function   RA_GetStats
+ *
+ *  @Description    gets stats on a given arena
+ *  
+ *  @Input  pArena - the arena the segment was originally allocated from.
+ *  @Input  ppszStr - string to write stats to 
+ *	@Input	pui32StrLen - length of string
+ *
+ *  @Return PVRSRV_ERROR
+ */
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+							IMG_CHAR **ppszStr, 
+							IMG_UINT32 *pui32StrLen);
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+								IMG_CHAR **ppszStr, 
+								IMG_UINT32 *pui32StrLen);
+
+#endif /* #ifdef RA_STATS */
+
+#endif
+
diff --git a/drivers/gpu/pvr/services4/srvkm/include/refcount.h b/drivers/gpu/pvr/services4/srvkm/include/refcount.h
new file mode 100644
index 0000000..95493b7
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/refcount.h
@@ -0,0 +1,293 @@
+/*************************************************************************/ /*!
+@Title          Services reference count debugging
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __REFCOUNT_H__
+#define __REFCOUNT_H__
+
+#include "pvr_bridge_km.h"
+#if defined(SUPPORT_ION)
+#include "ion_sync.h"
+#endif /* defined(SUPPORT_ION) */
+#if defined(SUPPORT_DMABUF)
+#include "dmabuf_sync.h"
+#endif /* defined(SUPPORT_DMABUF) */
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+void PVRSRVDumpRefCountCCB(void);
+
+#define PVRSRVKernelSyncInfoIncRef(x...) \
+	PVRSRVKernelSyncInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelSyncInfoDecRef(x...) \
+	PVRSRVKernelSyncInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoIncRef(x...) \
+	PVRSRVKernelMemInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoDecRef(x...) \
+	PVRSRVKernelMemInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncRef(x...) \
+	PVRSRVBMBufIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecRef(x...) \
+	PVRSRVBMBufDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncExport(x...) \
+	PVRSRVBMBufIncExport2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecExport(x...) \
+	PVRSRVBMBufDecExport2(__FILE__, __LINE__, x)
+
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								 PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+								 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								 PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+								 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile,
+						IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile,
+						IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile,
+						   IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile,
+						   IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+						  IMG_UINT32 ui32Index);
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+						  IMG_UINT32 ui32Index);
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+#define PVRSRVOffsetStructIncRef(x...) \
+	PVRSRVOffsetStructIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecRef(x...) \
+	PVRSRVOffsetStructDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructIncMapped(x...) \
+	PVRSRVOffsetStructIncMapped2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecMapped(x...) \
+	PVRSRVOffsetStructDecMapped2(__FILE__, __LINE__, x)
+
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+							   PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+							   PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								  PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+								  PKV_OFFSET_STRUCT psOffsetStruct);
+
+#if defined(SUPPORT_ION)
+#define PVRSRVIonBufferSyncInfoIncRef(x...) \
+	PVRSRVIonBufferSyncInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVIonBufferSyncInfoDecRef(x...) \
+	PVRSRVIonBufferSyncInfoDecRef2(__FILE__, __LINE__, x)
+
+PVRSRV_ERROR PVRSRVIonBufferSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+											IMG_HANDLE hUnique,
+											IMG_HANDLE hDevCookie,
+											IMG_HANDLE hDevMemContext,
+											PVRSRV_ION_SYNC_INFO **ppsIonSyncInfo,
+											PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVIonBufferSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+									PVRSRV_ION_SYNC_INFO *psIonSyncInfo,
+									PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+#endif /* defined (SUPPORT_ION) */
+
+#if defined(SUPPORT_DMABUF)
+#define PVRSRVDmaBufSyncInfoIncRef(x...) \
+	PVRSRVDmaBufSyncInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVDmaBufSyncInfoDecRef(x...) \
+	PVRSRVDmaBufSyncInfoDecRef2(__FILE__, __LINE__, x)
+
+PVRSRV_ERROR PVRSRVDmaBufSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+											IMG_HANDLE hUnique,
+											IMG_HANDLE hPriv,
+											IMG_HANDLE hDevCookie,
+											IMG_HANDLE hDevMemContext,
+											PVRSRV_DMABUF_SYNC_INFO **ppsDmaBufSyncInfo,
+											PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+void PVRSRVDmaBufSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+									PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo,
+									PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+#endif /* defined (SUPPORT_DMABUF) */
+
+#endif /* defined(__linux__) */
+
+#else /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+static INLINE void PVRSRVDumpRefCountCCB(void) { }
+
+static INLINE void PVRSRVKernelSyncInfoIncRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+								PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+	PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelSyncInfoDecRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+								PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+	PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelMemInfoIncRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	psKernelMemInfo->ui32RefCount++;
+}
+
+static INLINE void PVRSRVKernelMemInfoDecRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	psKernelMemInfo->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncRef(BM_BUF *pBuf)
+{
+	pBuf->ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMBufDecRef(BM_BUF *pBuf)
+{
+	pBuf->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncExport(BM_BUF *pBuf)
+{
+	pBuf->ui32ExportCount++;
+}
+
+static INLINE void PVRSRVBMBufDecExport(BM_BUF *pBuf)
+{
+	pBuf->ui32ExportCount--;
+}
+
+static INLINE void PVRSRVBMXProcIncRef(IMG_UINT32 ui32Index)
+{
+	gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMXProcDecRef(IMG_UINT32 ui32Index)
+{
+	gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+static INLINE void PVRSRVOffsetStructIncRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	psOffsetStruct->ui32RefCount++;
+}
+
+static INLINE void PVRSRVOffsetStructDecRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	psOffsetStruct->ui32RefCount--;
+}
+
+static INLINE void PVRSRVOffsetStructIncMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	psOffsetStruct->ui32Mapped++;
+}
+
+static INLINE void PVRSRVOffsetStructDecMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+	psOffsetStruct->ui32Mapped--;
+}
+
+#if defined(SUPPORT_ION)
+static INLINE PVRSRV_ERROR PVRSRVIonBufferSyncInfoIncRef(IMG_HANDLE hUnique,
+														 IMG_HANDLE hDevCookie,
+														 IMG_HANDLE hDevMemContext,
+														 PVRSRV_ION_SYNC_INFO **ppsIonSyncInfo,
+														 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+
+	return PVRSRVIonBufferSyncAcquire(hUnique,
+									  hDevCookie,
+									  hDevMemContext,
+									  ppsIonSyncInfo);
+}
+
+static INLINE void PVRSRVIonBufferSyncInfoDecRef(PVRSRV_ION_SYNC_INFO *psIonSyncInfo,
+										   PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+	PVRSRVIonBufferSyncRelease(psIonSyncInfo);
+}
+#endif	/* defined (SUPPORT_ION) */
+
+#if defined(SUPPORT_DMABUF)
+static INLINE PVRSRV_ERROR PVRSRVDmaBufSyncInfoIncRef(IMG_HANDLE hUnique,
+														 IMG_HANDLE hPriv,
+														 IMG_HANDLE hDevCookie,
+														 IMG_HANDLE hDevMemContext,
+														 PVRSRV_DMABUF_SYNC_INFO **ppsDmaBufSyncInfo,
+														 PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+
+	return PVRSRVDmaBufSyncAcquire(hUnique,
+									  hPriv,
+									  hDevCookie,
+									  hDevMemContext,
+									  ppsDmaBufSyncInfo);
+}
+
+static INLINE void PVRSRVDmaBufSyncInfoDecRef(PVRSRV_DMABUF_SYNC_INFO *psDmaBufSyncInfo,
+										   PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+	PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+	PVRSRVDmaBufSyncRelease(psDmaBufSyncInfo);
+}
+#endif	/* defined (SUPPORT_DMABUF) */
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+#endif /* __REFCOUNT_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/include/resman.h b/drivers/gpu/pvr/services4/srvkm/include/resman.h
new file mode 100644
index 0000000..14af110
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/resman.h
@@ -0,0 +1,153 @@
+/*************************************************************************/ /*!
+@Title          Resource Manager API
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	Provide resource management
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __RESMAN_H__
+#define __RESMAN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/******************************************************************************
+ * resman definitions 
+ *****************************************************************************/
+
+enum {
+	/* SGX: */
+	RESMAN_TYPE_SHARED_PB_DESC = 1,					/*!< Parameter buffer kernel stubs */
+	RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,				/*!< Shared parameter buffer creation lock */
+	RESMAN_TYPE_HW_RENDER_CONTEXT,					/*!< Hardware Render Context Resource */
+	RESMAN_TYPE_HW_TRANSFER_CONTEXT,				/*!< Hardware transfer Context Resource */
+	RESMAN_TYPE_HW_2D_CONTEXT,						/*!< Hardware 2D Context Resource */
+	RESMAN_TYPE_TRANSFER_CONTEXT,					/*!< Transfer Queue context */
+
+	/* VGX: */
+	RESMAN_TYPE_DMA_CLIENT_FIFO_DATA,				/*!< VGX DMA Client FIFO data */
+
+	/* DISPLAY CLASS: */
+	RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,			/*!< Display Class Swapchain Reference Resource */
+	RESMAN_TYPE_DISPLAYCLASS_DEVICE,				/*!< Display Class Device Resource */
+
+	/* BUFFER CLASS: */
+	RESMAN_TYPE_BUFFERCLASS_DEVICE,					/*!< Buffer Class Device Resource */
+	
+	/* OS specific User mode Mappings: */
+	RESMAN_TYPE_OS_USERMODE_MAPPING,				/*!< OS specific User mode mappings */
+	
+	/* COMMON: */
+	RESMAN_TYPE_DEVICEMEM_CONTEXT,					/*!< Device Memory Context Resource */
+	RESMAN_TYPE_DEVICECLASSMEM_MAPPING,				/*!< Device Memory Mapping Resource */
+	RESMAN_TYPE_DEVICEMEM_MAPPING,					/*!< Device Memory Mapping Resource */
+	RESMAN_TYPE_DEVICEMEM_WRAP,						/*!< Device Memory Wrap Resource */
+	RESMAN_TYPE_DEVICEMEM_ALLOCATION,				/*!< Device Memory Allocation Resource */
+	RESMAN_TYPE_DEVICEMEM_ION,						/*!< Device Memory Ion Resource */
+	RESMAN_TYPE_DEVICEMEM_DMABUF,						/*!< Device Memory dma-buf Resource */
+	RESMAN_TYPE_EVENT_OBJECT,						/*!< Event Object */
+    RESMAN_TYPE_SHARED_MEM_INFO,                    /*!< Shared system memory meminfo */
+    RESMAN_TYPE_MODIFY_SYNC_OPS,					/*!< Syncobject synchronisation Resource*/
+    RESMAN_TYPE_SYNC_INFO,					        /*!< Syncobject Resource*/
+	
+	/* KERNEL: */
+	RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION			/*!< Device Memory Allocation Resource */
+};
+
+#define RESMAN_CRITERIA_ALL				0x00000000	/*!< match by criteria all */
+#define RESMAN_CRITERIA_RESTYPE			0x00000001	/*!< match by criteria type */
+#define RESMAN_CRITERIA_PVOID_PARAM		0x00000002	/*!< match by criteria param1 */
+#define RESMAN_CRITERIA_UI32_PARAM		0x00000004	/*!< match by criteria param2 */
+
+typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup); 
+
+typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
+typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+
+/******************************************************************************
+ * resman functions 
+ *****************************************************************************/
+
+/*
+	Note:
+	Resource cleanup can fail with retry in which case we don't remove
+	it from resman's list and either UM or KM will try to release the
+	resource at a later date (and will keep trying until a non-retry
+	error is returned)
+*/
+
+PVRSRV_ERROR ResManInit(IMG_VOID);
+IMG_VOID ResManDeInit(IMG_VOID);
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT	hResManContext,
+							   IMG_UINT32		ui32ResType, 
+							   IMG_PVOID		pvParam, 
+							   IMG_UINT32		ui32Param, 
+							   RESMAN_FREE_FN	pfnFreeResource);
+
+PVRSRV_ERROR ResManFreeResByPtr(PRESMAN_ITEM	psResItem,
+								IMG_BOOL		bForceCleanup);
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT	hResManContext,
+									 IMG_UINT32			ui32SearchCriteria, 
+									 IMG_UINT32			ui32ResType, 
+									 IMG_PVOID			pvParam, 
+									 IMG_UINT32			ui32Param);
+
+PVRSRV_ERROR ResManDissociateRes(PRESMAN_ITEM		psResItem,
+							 PRESMAN_CONTEXT	psNewResManContext);
+
+PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT	hResManContext,
+									 PRESMAN_ITEM		psItem);
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE			hPerProc,
+								 PRESMAN_CONTEXT	*phResManContext);
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext,
+								IMG_BOOL		bKernelContext);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* __RESMAN_H__ */
+
+/******************************************************************************
+ End of file (resman.h)
+******************************************************************************/
+
diff --git a/drivers/gpu/pvr/services4/srvkm/include/services_headers.h b/drivers/gpu/pvr/services4/srvkm/include/services_headers.h
new file mode 100644
index 0000000..d09b8a8
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/services_headers.h
@@ -0,0 +1,68 @@
+/*************************************************************************/ /*!
+@Title          Command queues and synchronisation
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Internal structures and definitions for command queues and 
+                synchronisation
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+
+#ifndef SERVICES_HEADERS_H
+#define SERVICES_HEADERS_H
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG		1
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "power.h"
+#include "resman.h"
+#include "queue.h"
+#include "srvkm.h"
+#include "kerneldisplay.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "metrics.h"
+#include "osfunc.h"
+#include "refcount.h"
+
+#endif /* SERVICES_HEADERS_H */
+
diff --git a/drivers/gpu/pvr/services4/srvkm/include/srvkm.h b/drivers/gpu/pvr/services4/srvkm/include/srvkm.h
new file mode 100644
index 0000000..723037e
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/srvkm.h
@@ -0,0 +1,273 @@
+/*************************************************************************/ /*!
+@Title          Services kernel module internal header file
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef SRVKM_H
+#define SRVKM_H
+
+#include "servicesint.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+	/**	Use PVR_DPF() unless message is necessary in release build
+	 */
+	#ifdef PVR_DISABLE_LOGGING
+	#define PVR_LOG(X)
+	#else
+	/* PRQA S 3410 1 */ /* this macro requires no brackets in order to work */
+	#define PVR_LOG(X)			PVRSRVReleasePrintf X;
+	#endif
+
+	IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+	IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32	ui32PID, IMG_UINT32 ui32Flags);
+	IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32	ui32PID);
+
+	IMG_IMPORT IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID);
+
+#if defined(SUPPORT_PVRSRV_DEVICE_CLASS)
+	IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+#endif
+
+	PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave);
+
+	IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID);
+
+	IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDumpSyncs(IMG_BOOL bActiveOnly);
+
+#define SYNC_OP_CLASS_MASK			0x0000ffffUL
+#define SYNC_OP_CLASS_SHIFT			0
+#define SYNC_OP_CLASS_MODOBJ		(1<<0)
+#define SYNC_OP_CLASS_QUEUE			(1<<1)
+#define SYNC_OP_CLASS_KICKTA		(1<<2)
+#define SYNC_OP_CLASS_TQ_3D			(1<<3)
+#define SYNC_OP_CLASS_TQ_2D			(1<<4)
+#define SYNC_OP_CLASS_LINUX_FENCE		(1<<5)
+#define SYNC_OP_TYPE_MASK			0x00f0000UL
+#define SYNC_OP_TYPE_SHIFT			16
+#define SYNC_OP_TYPE_READOP			(1<<0)
+#define SYNC_OP_TYPE_WRITEOP		(1<<1)
+#define SYNC_OP_TYPE_READOP2		(1<<2)
+
+#define SYNC_OP_HAS_DATA			0x80000000UL
+#define SYNC_OP_TAKE				0x40000000UL
+#define SYNC_OP_ROLLBACK			0x20000000UL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncTakeWriteOp)
+#endif
+static INLINE
+IMG_UINT32 SyncTakeWriteOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSync, IMG_UINT32 ui32OpType)
+{
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+	IMG_UINT32 ui32Index = psKernelSync->ui32HistoryIndex;
+
+	/* Record a history of all the classes of operation taken on this sync */
+	psKernelSync->ui32OperationMask |= (ui32OpType & SYNC_OP_CLASS_MASK) >> SYNC_OP_CLASS_SHIFT;
+
+	/* Add this operation to the history buffer */
+	psKernelSync->aui32OpInfo[ui32Index] = SYNC_OP_HAS_DATA | ui32OpType | (SYNC_OP_TYPE_WRITEOP << SYNC_OP_TYPE_SHIFT) | SYNC_OP_TAKE;
+	psKernelSync->aui32ReadOpSample[ui32Index] = psKernelSync->psSyncData->ui32ReadOpsPending;
+	psKernelSync->aui32WriteOpSample[ui32Index] = psKernelSync->psSyncData->ui32WriteOpsPending;
+	psKernelSync->aui32ReadOp2Sample[ui32Index] = psKernelSync->psSyncData->ui32ReadOps2Pending;
+	psKernelSync->ui32HistoryIndex++;
+	psKernelSync->ui32HistoryIndex = psKernelSync->ui32HistoryIndex % PER_SYNC_HISTORY;
+#endif
+	PVR_UNREFERENCED_PARAMETER(ui32OpType);
+	return psKernelSync->psSyncData->ui32WriteOpsPending++;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncTakeReadOp)
+#endif
+static INLINE
+IMG_UINT32 SyncTakeReadOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSync, IMG_UINT32 ui32OpType)
+{
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+	IMG_UINT32 ui32Index = psKernelSync->ui32HistoryIndex;
+
+	/* Record a history of all the classes of operation taken on this sync */
+	psKernelSync->ui32OperationMask |= (ui32OpType & SYNC_OP_CLASS_MASK) >> SYNC_OP_CLASS_SHIFT;
+
+	/* Add this operation to the history buffer */
+	psKernelSync->aui32OpInfo[ui32Index] = SYNC_OP_HAS_DATA | ui32OpType | (SYNC_OP_TYPE_READOP << SYNC_OP_TYPE_SHIFT) | SYNC_OP_TAKE;
+	psKernelSync->aui32ReadOpSample[ui32Index] = psKernelSync->psSyncData->ui32ReadOpsPending;
+	psKernelSync->aui32WriteOpSample[ui32Index] = psKernelSync->psSyncData->ui32WriteOpsPending;
+	psKernelSync->aui32ReadOp2Sample[ui32Index] = psKernelSync->psSyncData->ui32ReadOps2Pending;
+	psKernelSync->ui32HistoryIndex++;
+	psKernelSync->ui32HistoryIndex = psKernelSync->ui32HistoryIndex % PER_SYNC_HISTORY;
+#endif
+	PVR_UNREFERENCED_PARAMETER(ui32OpType);
+	return psKernelSync->psSyncData->ui32ReadOpsPending++;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncTakeReadOp2)
+#endif
+static INLINE
+IMG_UINT32 SyncTakeReadOp2(PVRSRV_KERNEL_SYNC_INFO *psKernelSync, IMG_UINT32 ui32OpType)
+{
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+	IMG_UINT32 ui32Index = psKernelSync->ui32HistoryIndex;
+
+	/* Record a history of all the classes of operation taken on this sync */
+	psKernelSync->ui32OperationMask |= (ui32OpType & SYNC_OP_CLASS_MASK) >> SYNC_OP_CLASS_SHIFT;
+
+	/* Add this operation to the history buffer */
+	psKernelSync->aui32OpInfo[ui32Index] = SYNC_OP_HAS_DATA | ui32OpType | (SYNC_OP_TYPE_READOP2 << SYNC_OP_TYPE_SHIFT) | SYNC_OP_TAKE;
+	psKernelSync->aui32ReadOpSample[ui32Index] = psKernelSync->psSyncData->ui32ReadOpsPending;
+	psKernelSync->aui32WriteOpSample[ui32Index] = psKernelSync->psSyncData->ui32WriteOpsPending;
+	psKernelSync->aui32ReadOp2Sample[ui32Index] = psKernelSync->psSyncData->ui32ReadOps2Pending;
+	psKernelSync->ui32HistoryIndex++;
+	psKernelSync->ui32HistoryIndex = psKernelSync->ui32HistoryIndex % PER_SYNC_HISTORY;
+#endif
+	PVR_UNREFERENCED_PARAMETER(ui32OpType);
+	return psKernelSync->psSyncData->ui32ReadOps2Pending++;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncRollBackWriteOp)
+#endif
+static INLINE
+IMG_UINT32 SyncRollBackWriteOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSync, IMG_UINT32 ui32OpType)
+{
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+	IMG_UINT32 ui32Index = psKernelSync->ui32HistoryIndex;
+
+	/* Record a history of all the classes of operation taken on this sync */
+	psKernelSync->ui32OperationMask |= (ui32OpType & SYNC_OP_CLASS_MASK) >> SYNC_OP_CLASS_SHIFT;
+
+	/* Add this operation to the history buffer */
+	psKernelSync->aui32OpInfo[ui32Index] = SYNC_OP_HAS_DATA | ui32OpType | (SYNC_OP_TYPE_WRITEOP << SYNC_OP_TYPE_SHIFT) | SYNC_OP_ROLLBACK;
+	psKernelSync->aui32ReadOpSample[ui32Index] = psKernelSync->psSyncData->ui32ReadOpsPending;
+	psKernelSync->aui32WriteOpSample[ui32Index] = psKernelSync->psSyncData->ui32WriteOpsPending;
+	psKernelSync->aui32ReadOp2Sample[ui32Index] = psKernelSync->psSyncData->ui32ReadOps2Pending;
+	psKernelSync->ui32HistoryIndex++;
+	psKernelSync->ui32HistoryIndex = psKernelSync->ui32HistoryIndex % PER_SYNC_HISTORY;
+#endif
+	PVR_UNREFERENCED_PARAMETER(ui32OpType);
+	return psKernelSync->psSyncData->ui32WriteOpsPending--;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SyncRollBackReadOp)
+#endif
+static INLINE
+IMG_UINT32 SyncRollBackReadOp(PVRSRV_KERNEL_SYNC_INFO *psKernelSync, IMG_UINT32 ui32OpType)
+{
+#if defined(SUPPORT_PER_SYNC_DEBUG)
+	IMG_UINT32 ui32Index = psKernelSync->ui32HistoryIndex;
+
+	/* Record a history of all the classes of operation taken on this sync */
+	psKernelSync->ui32OperationMask |= (ui32OpType & SYNC_OP_CLASS_MASK) >> SYNC_OP_CLASS_SHIFT;
+
+	/* Add this operation to the history buffer */
+	psKernelSync->aui32OpInfo[ui32Index] = SYNC_OP_HAS_DATA | ui32OpType | (SYNC_OP_TYPE_READOP << SYNC_OP_TYPE_SHIFT) | SYNC_OP_ROLLBACK;
+	psKernelSync->aui32ReadOpSample[ui32Index] = psKernelSync->psSyncData->ui32ReadOpsPending;
+	psKernelSync->aui32WriteOpSample[ui32Index] = psKernelSync->psSyncData->ui32WriteOpsPending;
+	psKernelSync->aui32ReadOp2Sample[ui32Index] = psKernelSync->psSyncData->ui32ReadOps2Pending;
+	psKernelSync->ui32HistoryIndex++;
+	psKernelSync->ui32HistoryIndex = psKernelSync->ui32HistoryIndex % PER_SYNC_HISTORY;
+#endif
+	PVR_UNREFERENCED_PARAMETER(ui32OpType);
+	return psKernelSync->psSyncData->ui32ReadOpsPending--;
+}
+
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+/******************
+HIGHER LEVEL MACROS
+*******************/
+
+/*----------------------------------------------------------------------------
+Repeats the body of the loop for a certain minimum time, or until the body
+exits by its own means (break, return, goto, etc.)
+
+Example of usage:
+
+LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+{
+	if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+	{
+		bTimeout = IMG_FALSE;
+		break;
+	}
+	
+	OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+} END_LOOP_UNTIL_TIMEOUT();
+
+-----------------------------------------------------------------------------*/
+
+/*	uiNotLastLoop will remain at 1 until the timeout has expired, at which time		
+ * 	it will be decremented and the loop executed one final time. This is necessary
+ *	when preemption is enabled. 
+ */
+/* PRQA S 3411,3431 12 */ /* critical format, leave alone */
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{\
+	IMG_UINT32 uiOffset, uiStart, uiCurrent; \
+	IMG_INT32 iNotLastLoop;					 \
+	for(uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart + 1, iNotLastLoop = 1;\
+		((uiCurrent - uiStart + uiOffset) < (TIMEOUT)) || iNotLastLoop--;				\
+		uiCurrent = OSClockus(),													\
+		uiOffset = uiCurrent < uiStart ? IMG_UINT32_MAX - uiStart : uiOffset,		\
+		uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+
+/*!
+ ******************************************************************************
+
+ @Function		PVRSRVGetErrorStringKM
+
+ @Description	Returns a text string relating to the PVRSRV_ERROR enum.
+
+ ******************************************************************************/
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
+
+#endif /* SRVKM_H */
diff --git a/drivers/gpu/pvr/services4/srvkm/include/ttrace.h b/drivers/gpu/pvr/services4/srvkm/include/ttrace.h
new file mode 100644
index 0000000..cb70ff8
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/ttrace.h
@@ -0,0 +1,200 @@
+/*************************************************************************/ /*!
+@Title          Timed Trace header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	Timed Trace header. Contines structures and functions used
+                in the timed trace subsystem.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#include "services_headers.h"
+#include "ttrace_common.h"
+#include "ttrace_tokens.h"
+
+#ifndef __TTRACE_H__
+#define __TTRACE_H__
+
+#if defined(TTRACE)
+
+	#define PVR_TTRACE(group, class, token) \
+			PVRSRVTimeTrace(group, class, token)
+	#define PVR_TTRACE_UI8(group, class, token, val) \
+			PVRSRVTimeTraceUI8(group, class, token, val)
+	#define PVR_TTRACE_UI16(group, class, token, val) \
+			PVRSRVTimeTraceUI16(group, class, token, val)
+	#define PVR_TTRACE_UI32(group, class, token, val) \
+			PVRSRVTimeTraceUI32(group, class, token, val)
+	#define PVR_TTRACE_UI64(group, class, token, val) \
+			PVRSRVTimeTraceUI64(group, class, token, val)
+	#define PVR_TTRACE_DEV_VIRTADDR(group, class, token, val) \
+			PVRSRVTimeTraceDevVirtAddr(group, class, token, val)
+	#define PVR_TTRACE_CPU_PHYADDR(group, class, token, val) \
+			PVRSRVTimeTraceCpuPhyAddr(group, class, token, val)
+	#define PVR_TTRACE_DEV_PHYADDR(group, class, token, val) \
+			PVRSRVTimeTraceDevPhysAddr(group, class, token, val)
+	#define PVR_TTRACE_SYS_PHYADDR(group, class, token, val) \
+			PVRSRVTimeTraceSysPhysAddr(group, class, token, val)
+	#define PVR_TTRACE_SYNC_OBJECT(group, token, syncobj, op) \
+			PVRSRVTimeTraceSyncObject(group, token, syncobj, op)
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTimeTraceArray(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+							IMG_UINT32 ui32Token, IMG_UINT32 ui32TypeSize,
+							IMG_UINT32 ui32Count, IMG_UINT8 *ui8Data);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTrace)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTrace(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, 0, 0, NULL);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI8)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI8(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_UINT8 ui8Value)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI8,
+				1, &ui8Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI16)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI16(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_UINT16 ui16Value)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI16,
+				1, (IMG_UINT8 *) &ui16Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI32)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI32(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_UINT32 ui32Value)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+				1, (IMG_UINT8 *) &ui32Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceUI64)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceUI64(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_UINT64 ui64Value)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI64,
+				1, (IMG_UINT8 *) &ui64Value);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceDevVirtAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceDevVirtAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_DEV_VIRTADDR psVAddr)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+				1, (IMG_UINT8 *) &psVAddr.uiAddr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceCpuPhyAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceCpuPhyAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_CPU_PHYADDR psPAddr)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+				1, (IMG_UINT8 *) &psPAddr.uiAddr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceDevPhysAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceDevPhysAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_DEV_PHYADDR psPAddr)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, PVRSRV_TRACE_TYPE_UI32,
+				1, (IMG_UINT8 *) &psPAddr.uiAddr);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVTimeTraceSysPhysAddr)
+#endif
+static INLINE IMG_VOID PVRSRVTimeTraceSysPhysAddr(IMG_UINT32 ui32Group, IMG_UINT32 ui32Class,
+						IMG_UINT32 ui32Token, IMG_SYS_PHYADDR psPAddr)
+{
+	PVRSRVTimeTraceArray(ui32Group, ui32Class, ui32Token, sizeof(psPAddr.uiAddr),
+				1, (IMG_UINT8 *) &psPAddr.uiAddr);
+}
+
+#else /* defined(PVRSRV_NEED_PVR_TIME_TRACE) */
+
+	#define PVR_TTRACE(group, class, token) \
+			((void) 0)
+	#define PVR_TTRACE_UI8(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_UI16(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_UI32(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_UI64(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_DEV_VIRTADDR(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_CPU_PHYADDR(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_DEV_PHYADDR(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_SYS_PHYADDR(group, class, token, val) \
+			((void) 0)
+	#define PVR_TTRACE_SYNC_OBJECT(group, token, syncobj, op) \
+			((void) 0)
+
+#endif /* defined(PVRSRV_NEED_PVR_TIME_TRACE) */
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceInit(IMG_VOID);
+IMG_IMPORT IMG_VOID PVRSRVTimeTraceDeinit(IMG_VOID);
+
+IMG_IMPORT IMG_VOID PVRSRVTimeTraceSyncObject(IMG_UINT32 ui32Group, IMG_UINT32 ui32Token,
+					      PVRSRV_KERNEL_SYNC_INFO *psSync, IMG_UINT8 ui8SyncOp);
+IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceBufferCreate(IMG_UINT32 ui32PID);
+IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID);
+
+IMG_IMPORT IMG_VOID PVRSRVDumpTimeTraceBuffers(IMG_VOID);
+#endif /* __TTRACE_H__ */
diff --git a/drivers/gpu/pvr/services4/srvkm/include/ttrace_common.h b/drivers/gpu/pvr/services4/srvkm/include/ttrace_common.h
new file mode 100644
index 0000000..e149c20
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/ttrace_common.h
@@ -0,0 +1,151 @@
+/*************************************************************************/ /*!
+@Title          Timed Trace header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	Timed Trace common header. Contains shared defines and 
+                structures which are shared with the post processing tool.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#include "img_types.h"
+
+#ifndef __TTRACE_COMMON_H__
+#define __TTRACE_COMMON_H__
+
+/*
+ * Trace item
+ * ==========
+ *
+ * A trace item contains a trace header, a timestamp, a UID and a
+ * data header all of which are 32-bit and mandatory. If there
+ * is no data then the data header size is set to 0.
+ *
+ * Trace header
+ * ------------
+ * 31   27   23   19   15   11   7    3
+ * GGGG GGGG CCCC CCCC TTTT TTTT TTTT TTTT
+ *
+ * G = group
+ *     Note:
+ *     Group 0xff means the message is padding
+ *
+ * C = class
+ * T = Token
+ *
+ * Data header
+ *-----------
+ * 31   27   23   19   15   11   7    3
+ * SSSS SSSS SSSS SSSS TTTT CCCC CCCC CCCC
+ *
+ * S = data packet size
+ * T = Type
+ *		0000 - 8 bit
+ *		0001 - 16 bit
+ *		0010 - 32 bit
+ *		0011 - 64 bit
+ *
+ * C = data item count
+ *
+ * Note: It might look strange having both the packet
+ *       size and the data item count, but the idea
+ *       is the you might have a "special" data type
+ *       who's size might not be known by the post
+ *       processing program and rather then fail
+ *       processing the buffer after that point if we
+ *       know the size we can just skip it and move to
+ *       the next item.
+ */
+
+
+#define PVRSRV_TRACE_HEADER		0
+#define PVRSRV_TRACE_TIMESTAMP		1
+#define PVRSRV_TRACE_HOSTUID		2
+#define PVRSRV_TRACE_DATA_HEADER	3
+#define PVRSRV_TRACE_DATA_PAYLOAD	4
+
+#define PVRSRV_TRACE_ITEM_SIZE		16
+
+#define PVRSRV_TRACE_GROUP_MASK		0xff
+#define PVRSRV_TRACE_CLASS_MASK		0xff
+#define PVRSRV_TRACE_TOKEN_MASK		0xffff
+
+#define PVRSRV_TRACE_GROUP_SHIFT	24
+#define PVRSRV_TRACE_CLASS_SHIFT	16
+#define PVRSRV_TRACE_TOKEN_SHIFT	0
+
+#define PVRSRV_TRACE_SIZE_MASK		0xffff
+#define PVRSRV_TRACE_TYPE_MASK		0xf
+#define PVRSRV_TRACE_COUNT_MASK		0xfff
+
+#define PVRSRV_TRACE_SIZE_SHIFT		16
+#define PVRSRV_TRACE_TYPE_SHIFT		12
+#define PVRSRV_TRACE_COUNT_SHIFT	0
+
+
+#define WRITE_HEADER(n,m) \
+	((m & PVRSRV_TRACE_##n##_MASK) << PVRSRV_TRACE_##n##_SHIFT)
+
+#define READ_HEADER(n,m) \
+	((m & (PVRSRV_TRACE_##n##_MASK << PVRSRV_TRACE_##n##_SHIFT)) >> PVRSRV_TRACE_##n##_SHIFT)
+
+
+#if defined(TTRACE_LARGE_BUFFER)
+#define TIME_TRACE_BUFFER_SIZE		8192
+#else
+#define TIME_TRACE_BUFFER_SIZE		4096
+#endif
+
+/* Type defines for trace items */
+#define PVRSRV_TRACE_TYPE_UI8		0
+#define PVRSRV_TRACE_TYPE_UI16		1
+#define PVRSRV_TRACE_TYPE_UI32		2
+#define PVRSRV_TRACE_TYPE_UI64		3
+
+#define PVRSRV_TRACE_TYPE_SYNC		15
+ #define PVRSRV_TRACE_SYNC_UID		0
+ #define PVRSRV_TRACE_SYNC_WOP		1
+ #define PVRSRV_TRACE_SYNC_WOC		2
+ #define PVRSRV_TRACE_SYNC_ROP		3
+ #define PVRSRV_TRACE_SYNC_ROC		4
+ #define PVRSRV_TRACE_SYNC_WO_DEV_VADDR	5
+ #define PVRSRV_TRACE_SYNC_RO_DEV_VADDR	6
+ #define PVRSRV_TRACE_SYNC_OP		7
+ #define PVRSRV_TRACE_SYNC_RO2P		8
+ #define PVRSRV_TRACE_SYNC_RO2C		9
+ #define PVRSRV_TRACE_SYNC_RO2_DEV_VADDR 10
+#define PVRSRV_TRACE_TYPE_SYNC_SIZE	((PVRSRV_TRACE_SYNC_RO2_DEV_VADDR + 1) * sizeof(IMG_UINT32))
+
+#endif /* __TTRACE_COMMON_H__*/
diff --git a/drivers/gpu/pvr/services4/srvkm/include/ttrace_tokens.h b/drivers/gpu/pvr/services4/srvkm/include/ttrace_tokens.h
new file mode 100644
index 0000000..5f89849
--- /dev/null
+++ b/drivers/gpu/pvr/services4/srvkm/include/ttrace_tokens.h
@@ -0,0 +1,135 @@
+/*************************************************************************/ /*!
+@Title          Timed Trace header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description	Timed Trace token header. Contains defines for all the tokens 
+                used.
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef __TTRACE_TOKENS_H__
+#define __TTRACE_TOKENS_H__
+
+/* All defines should use decimal so to not confuse the post processing tool */
+
+/* Trace groups */
+#define PVRSRV_TRACE_GROUP_KICK		0
+#define PVRSRV_TRACE_GROUP_TRANSFER	1
+#define PVRSRV_TRACE_GROUP_QUEUE	2
+#define PVRSRV_TRACE_GROUP_POWER	3
+#define PVRSRV_TRACE_GROUP_MKSYNC	4
+#define PVRSRV_TRACE_GROUP_MODOBJ	5
+
+#define PVRSRV_TRACE_GROUP_PADDING	255
+
+/* Trace classes */
+#define PVRSRV_TRACE_CLASS_FUNCTION_ENTER	0
+#define PVRSRV_TRACE_CLASS_FUNCTION_EXIT	1
+#define PVRSRV_TRACE_CLASS_SYNC				2
+#define PVRSRV_TRACE_CLASS_CCB				3
+#define PVRSRV_TRACE_CLASS_CMD_START		4
+#define PVRSRV_TRACE_CLASS_CMD_END			5
+#define PVRSRV_TRACE_CLASS_CMD_COMP_START	6
+#define PVRSRV_TRACE_CLASS_CMD_COMP_END		7
+#define PVRSRV_TRACE_CLASS_FLAGS			8
+#define PVRSRV_TRACE_CLASS_DEVVADDR			9
+#define PVRSRV_TRACE_CLASS_FRAMENUM			10
+ 
+#define PVRSRV_TRACE_CLASS_NONE				255
+
+/* Operation about to happen on the sync object */
+#define PVRSRV_SYNCOP_SAMPLE		0
+#define PVRSRV_SYNCOP_COMPLETE		1
+#define PVRSRV_SYNCOP_DUMP			2
+
+/*
+ * Trace tokens
+ * ------------
+ * These only need to unique within a group.
+ */
+
+/* Kick group tokens */
+#define KICK_TOKEN_DOKICK			0
+#define KICK_TOKEN_CCB_OFFSET		1
+#define KICK_TOKEN_TA3D_SYNC		2
+#define KICK_TOKEN_TA_SYNC			3
+#define KICK_TOKEN_3D_SYNC			4
+#define KICK_TOKEN_SRC_SYNC			5
+#define KICK_TOKEN_DST_SYNC			6
+#define KICK_TOKEN_FIRST_KICK		7
+#define KICK_TOKEN_LAST_KICK		8
+#define KICK_TOKEN_HWRTDATASET		9
+#define KICK_TOKEN_HWRTDATA			10
+#define KICK_TOKEN_FRAMENUM			11
+#define KICK_TOKEN_RENDERCONTEXT	12
+
+/* Transfer Queue group tokens */
+#define TRANSFER_TOKEN_SUBMIT		0
+#define TRANSFER_TOKEN_TA_SYNC		1
+#define TRANSFER_TOKEN_3D_SYNC		2
+#define TRANSFER_TOKEN_SRC_SYNC		3
+#define TRANSFER_TOKEN_DST_SYNC		4
+#define TRANSFER_TOKEN_CCB_OFFSET	5
+
+/* Queue group tokens */
+#define QUEUE_TOKEN_GET_SPACE			0
+#define QUEUE_TOKEN_INSERTKM			1
+#define QUEUE_TOKEN_SUBMITKM			2
+#define QUEUE_TOKEN_PROCESS_COMMAND		3
+#define QUEUE_TOKEN_PROCESS_QUEUES		4
+#define QUEUE_TOKEN_COMMAND_COMPLETE	5
+#define QUEUE_TOKEN_UPDATE_DST			6
+#define QUEUE_TOKEN_UPDATE_SRC			7
+#define QUEUE_TOKEN_SRC_SYNC			8
+#define QUEUE_TOKEN_DST_SYNC			9
+#define QUEUE_TOKEN_COMMAND_TYPE		10
+
+/* uKernel Sync tokens */
+#define MKSYNC_TOKEN_KERNEL_CCB_OFFSET	0
+#define MKSYNC_TOKEN_CORE_CLK			1
+#define MKSYNC_TOKEN_UKERNEL_CLK		2
+
+/* ModObj tokens */
+#define MODOBJ_TOKEN_MODIFY_PENDING		0
+#define MODOBJ_TOKEN_COMPLETE_PENDING	1
+#define MODOBJ_TOKEN_READ_SYNC			2
+#define MODOBJ_TOKEN_WRITE_SYNC			3
+#define MODOBJ_TOKEN_READ_WRITE_SYNC	4
+#define MODOBJ_TOKEN_SYNC_UPDATE		5
+#define MODOBJ_TOKEN_READ2_SYNC			6
+
+#endif /* __TTRACE_TOKENS_H__ */
diff --git a/drivers/gpu/pvr/services4/system/include/syscommon.h b/drivers/gpu/pvr/services4/system/include/syscommon.h
new file mode 100644
index 0000000..79cdee3
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/include/syscommon.h
@@ -0,0 +1,393 @@
+/*************************************************************************/ /*!
+@Title          Common System APIs and structures
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    This header provides common system-specific declarations and macros
+                that are supported by all system's
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#ifndef _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "sysconfig.h"      /* System specific system defines */
+#include "sysinfo.h"		/* globally accessible system info */
+#include "servicesint.h"
+#include "queue.h"
+#include "power.h"
+#include "resman.h"
+#include "ra.h"
+#include "device.h"
+#include "buffer_manager.h"
+#include "pvr_debug.h"
+#include "services.h"
+
+#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
+#include <asm/io.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ ****************************************************************************
+	device id management structure
+ ****************************************************************************/
+typedef struct _SYS_DEVICE_ID_TAG
+{
+	IMG_UINT32	uiID;
+	IMG_BOOL	bInUse;
+
+} SYS_DEVICE_ID;
+
+
+/*
+	the max number of independent local backing stores services supports
+	(grow this number if ever required)
+*/
+#define SYS_MAX_LOCAL_DEVMEM_ARENAS	4
+
+typedef IMG_HANDLE (*PFN_HTIMER_CREATE) (IMG_VOID);
+typedef IMG_UINT32 (*PFN_HTIMER_GETUS) (IMG_HANDLE);
+typedef IMG_VOID (*PFN_HTIMER_DESTROY) (IMG_HANDLE);
+/*!
+ ****************************************************************************
+	Top level system data structure
+ ****************************************************************************/
+typedef struct _SYS_DATA_TAG_
+{
+    IMG_UINT32                  ui32NumDevices;      	   	/*!< number of devices in system */
+	SYS_DEVICE_ID				sDeviceID[SYS_DEVICE_COUNT];
+    PVRSRV_DEVICE_NODE			*psDeviceNodeList;			/*!< list of private device info structures */
+    PVRSRV_POWER_DEV			*psPowerDeviceList;			/*!< list of devices registered with the power manager */
+	PVRSRV_RESOURCE				sPowerStateChangeResource;	/*!< lock for power state transitions */
+   	PVRSRV_SYS_POWER_STATE		eCurrentPowerState;			/*!< current Kernel services power state */
+   	PVRSRV_SYS_POWER_STATE		eFailedPowerState;			/*!< Kernel services power state (Failed to transition to) */
+   	IMG_UINT32		 			ui32CurrentOSPowerState;	/*!< current OS specific power state */
+    PVRSRV_QUEUE_INFO           *psQueueList;           	/*!< list of all command queues in the system */
+   	PVRSRV_KERNEL_SYNC_INFO 	*psSharedSyncInfoList;		/*!< list of cross process syncinfos */
+    IMG_PVOID                   pvEnvSpecificData;      	/*!< Environment specific data */
+    IMG_PVOID                   pvSysSpecificData;    	  	/*!< Unique to system, accessible at system layer only */
+	PVRSRV_RESOURCE				sQProcessResource;			/*!< Command Q processing access lock */
+	IMG_VOID					*pvSOCRegsBase;				/*!< SOC registers base linear address */
+    IMG_HANDLE                  hSOCTimerRegisterOSMemHandle; /*!< SOC Timer register (if present) */
+	IMG_UINT32					*pvSOCTimerRegisterKM;		/*!< SOC Timer register (if present) */
+	IMG_VOID					*pvSOCClockGateRegsBase;	/*!< SOC Clock gating registers (if present) */
+	IMG_UINT32					ui32SOCClockGateRegsSize;
+															
+	struct _DEVICE_COMMAND_DATA_ *apsDeviceCommandData[SYS_DEVICE_COUNT];
+															/*!< command complete data and callback function store for every command for every device */
+
+	RA_ARENA					*apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS]; /*!< RA Arenas for local device memory heap management */
+
+    IMG_CHAR                    *pszVersionString;          /*!< Human readable string showing relevent system version info */
+#if defined(SUPPORT_TI_VERSION_STRING)
+	IMG_CHAR 		szTIVersion[64];
+#endif
+	PVRSRV_EVENTOBJECT			*psGlobalEventObject;		/*!< OS Global Event Object */
+
+	PVRSRV_MISC_INFO_CPUCACHEOP_TYPE ePendingCacheOpType;	/*!< Deferred CPU cache op control */
+
+	PFN_HTIMER_CREATE	pfnHighResTimerCreate;
+	PFN_HTIMER_GETUS	pfnHighResTimerGetus;
+	PFN_HTIMER_DESTROY	pfnHighResTimerDestroy;
+} SYS_DATA;
+
+
+/****************************************************************************
+ *	common function prototypes
+ ****************************************************************************/
+
+#if defined (CUSTOM_DISPLAY_SEGMENT)
+PVRSRV_ERROR SysGetDisplaySegmentAddress (IMG_VOID *pvDevInfo, IMG_VOID *pvPhysicalAddress, IMG_UINT32 *pui32Length);
+#endif
+
+PVRSRV_ERROR SysInitialise(IMG_VOID);
+PVRSRV_ERROR SysFinalise(IMG_VOID);
+
+PVRSRV_ERROR SysDeinitialise(SYS_DATA *psSysData);
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+									IMG_VOID **ppvDeviceMap);
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA			*psSysData,
+								 PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits);
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+									PVRSRV_DEV_POWER_STATE eNewPowerState,
+									PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+									 PVRSRV_DEV_POWER_STATE eNewPowerState,
+									 PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+IMG_VOID SysSGXIdleEntered(IMG_VOID);
+IMG_VOID SysSGXCommandPending(IMG_BOOL bSGXIdle);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(IMG_BOOL bTryLock);
+IMG_VOID SysPowerLockUnwrap(IMG_VOID);
+#endif
+
+PVRSRV_ERROR SysOEMFunction (	IMG_UINT32	ui32ID,
+								IMG_VOID	*pvIn,
+								IMG_UINT32  ulInSize,
+								IMG_VOID	*pvOut,
+								IMG_UINT32	ulOutSize);
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR cpu_paddr);
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR SysPAddr);
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr);
+#if defined(PVR_LMA)
+IMG_BOOL SysVerifyCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR CpuPAddr);
+IMG_BOOL SysVerifySysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+#endif
+
+extern SYS_DATA* gpsSysData;
+
+
+#if !defined(USE_CODE)
+
+/*!
+******************************************************************************
+
+ @Function	SysAcquireData
+
+ @Description returns reference to to sysdata
+ 				creating one on first call
+
+ @Input    ppsSysData - pointer to copy reference into
+
+ @Return   ppsSysData updated
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireData)
+#endif
+static INLINE IMG_VOID SysAcquireData(SYS_DATA **ppsSysData)
+{
+	/* Copy pointer back system information pointer */
+	*ppsSysData = gpsSysData;
+
+	/*
+		Verify we've not been called before being initialised. Instinctively
+		we should do this check first, but in the failing case we'll just write
+		null back and the compiler won't warn about an uninitialised varible.
+	*/
+	PVR_ASSERT (gpsSysData != IMG_NULL);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysAcquireDataNoCheck
+
+ @Description returns reference to to sysdata
+ 				creating one on first call
+
+ @Input    none
+
+ @Return   psSysData - pointer to copy reference into
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireDataNoCheck)
+#endif
+static INLINE SYS_DATA * SysAcquireDataNoCheck(IMG_VOID)
+{
+	/* return pointer back system information pointer */
+	return gpsSysData;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysInitialiseCommon
+
+ @Description Performs system initialisation common to all systems
+
+ @Input    psSysData - pointer to system data
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysInitialiseCommon)
+#endif
+static INLINE PVRSRV_ERROR SysInitialiseCommon(SYS_DATA *psSysData)
+{
+	PVRSRV_ERROR	eError;
+
+	/* Initialise Services */
+	eError = PVRSRVInit(psSysData);
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	SysDeinitialiseCommon
+
+ @Description Performs system deinitialisation common to all systems
+
+ @Input    psSysData - pointer to system data
+
+ @Return   PVRSRV_ERROR  :
+
+******************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDeinitialiseCommon)
+#endif
+static INLINE IMG_VOID SysDeinitialiseCommon(SYS_DATA *psSysData)
+{
+	/* De-initialise Services */
+	PVRSRVDeInit(psSysData);
+
+	OSDestroyResource(&psSysData->sPowerStateChangeResource);
+}
+#endif /* !defined(USE_CODE) */
+
+
+/*
+ * SysReadHWReg and SysWriteHWReg differ from OSReadHWReg and OSWriteHWReg
+ * in that they are always intended for use with real hardware, even on
+ * NO_HARDWARE systems.
+ */
+#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
+#define	SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else	/* !(defined(NO_HARDWARE) && defined(__linux__)) */
+/*!
+******************************************************************************
+
+ @Function	SysReadHWReg
+
+ @Description
+
+ register read function
+
+ @input pvLinRegBaseAddr :	lin addr of register block base
+
+ @input ui32Offset :
+
+ @Return   register value
+
+******************************************************************************/
+static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+	return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+/*!
+******************************************************************************
+
+ @Function	SysWriteHWReg
+
+ @Description
+
+ register write function
+
+ @input pvLinRegBaseAddr :	lin addr of register block base
+
+ @input ui32Offset :
+
+ @input ui32Value :
+
+ @Return   none
+
+******************************************************************************/
+static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+	writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif	/* !(defined(NO_HARDWARE) && defined(__linux__)) */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysHighResTimerCreate)
+#endif
+static INLINE IMG_HANDLE SysHighResTimerCreate(IMG_VOID)
+{
+	SYS_DATA *psSysData;
+
+	SysAcquireData(&psSysData);
+	return psSysData->pfnHighResTimerCreate();
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysHighResTimerGetus)
+#endif
+static INLINE IMG_UINT32 SysHighResTimerGetus(IMG_HANDLE hTimer)
+{
+	SYS_DATA *psSysData;
+
+	SysAcquireData(&psSysData);
+	return psSysData->pfnHighResTimerGetus(hTimer);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysHighResTimerDestroy)
+#endif
+static INLINE IMG_VOID SysHighResTimerDestroy(IMG_HANDLE hTimer)
+{
+	SYS_DATA *psSysData;
+
+	SysAcquireData(&psSysData);
+	psSysData->pfnHighResTimerDestroy(hTimer);
+}
+#endif
+
+/*****************************************************************************
+ End of file (syscommon.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/services4/system/omap/oemfuncs.h b/drivers/gpu/pvr/services4/system/omap/oemfuncs.h
new file mode 100644
index 0000000..0902042
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/oemfuncs.h
@@ -0,0 +1,80 @@
+/*************************************************************************/ /*!
+@Title          SGX kernel/client driver interface structures and prototypes
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/* function in/out data structures: */
+typedef IMG_UINT32   (*PFN_SRV_BRIDGEDISPATCH)( IMG_UINT32  Ioctl,
+												IMG_BYTE   *pInBuf,
+												IMG_UINT32  InBufLen, 
+											    IMG_BYTE   *pOutBuf,
+												IMG_UINT32  OutBufLen,
+												IMG_UINT32 *pdwBytesTransferred);
+/*
+	Function table for kernel 3rd party driver to kernel services
+*/
+typedef struct PVRSRV_DC_OEM_JTABLE_TAG
+{
+	PFN_SRV_BRIDGEDISPATCH			pfnOEMBridgeDispatch;
+	IMG_PVOID						pvDummy1;
+	IMG_PVOID						pvDummy2;
+	IMG_PVOID						pvDummy3;
+
+} PVRSRV_DC_OEM_JTABLE;
+
+#define OEM_GET_EXT_FUNCS			(1<<1)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif	/* __OEMFUNCS_H__ */
+
+/*****************************************************************************
+ End of file (oemfuncs.h)
+*****************************************************************************/
+
+
diff --git a/drivers/gpu/pvr/services4/system/omap/sgxfreq.c b/drivers/gpu/pvr/services4/system/omap/sgxfreq.c
new file mode 100644
index 0000000..6e5571e
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sgxfreq.c
@@ -0,0 +1,846 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc
+ *
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+#include <linux/pm_opp.h>
+#include <linux/of.h>
+#else
+#include <linux/opp.h>
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
+#include <plat/gpu.h>
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+#include <linux/pm_voltage_domain.h>
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+#include <linux/regulator/consumer.h>
+#endif
+
+#include "sgxfreq.h"
+
+static struct sgxfreq_data {
+	int freq_cnt;
+	unsigned long *freq_list;
+	unsigned long freq;
+	unsigned long freq_request;
+	unsigned long freq_limit;
+	unsigned long total_idle_time;
+	unsigned long total_active_time;
+	struct mutex freq_mutex;
+	struct list_head gov_list;
+	struct sgxfreq_governor *gov;
+	struct mutex gov_mutex;
+	struct sgxfreq_sgx_data sgx_data;
+	struct device *dev;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
+	struct gpu_platform_data *pdata;
+#else
+	struct clk *core_clk;
+	struct clk *gpu_clk;
+	struct clk *per_clk;
+	struct clk *gpu_core_clk;
+	struct clk *gpu_hyd_clk;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+	struct regulator *gpu_reg;
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+	struct notifier_block *clk_nb;
+#endif
+#endif
+} sfd;
+
+/* Governor init/deinit functions */
+int onoff_init(void);
+int onoff_deinit(void);
+int activeidle_init(void);
+int activeidle_deinit(void);
+int on3demand_init(void);
+int on3demand_deinit(void);
+int userspace_init(void);
+int userspace_deinit(void);
+
+
+typedef int sgxfreq_gov_init_t(void);
+sgxfreq_gov_init_t *sgxfreq_gov_init[] = {
+	onoff_init,
+	activeidle_init,
+	on3demand_init,
+	userspace_init,
+	NULL,
+};
+
+typedef int sgxfreq_gov_deinit_t(void);
+sgxfreq_gov_deinit_t *sgxfreq_gov_deinit[] = {
+	onoff_deinit,
+	activeidle_deinit,
+	on3demand_deinit,
+	userspace_deinit,
+	NULL,
+};
+
+#define SGXFREQ_DEFAULT_GOV_NAME "on3demand"
+static unsigned long _idle_curr_time;
+static unsigned long _idle_prev_time;
+static unsigned long _active_curr_time;
+static unsigned long _active_prev_time;
+
+#if (defined(CONFIG_THERMAL) || defined(CONFIG_THERMAL_FRAMEWORK))
+int cool_init(void);
+void cool_deinit(void);
+#endif
+
+/*********************** begin sysfs interface ***********************/
+
+struct kobject *sgxfreq_kobj;
+
+static ssize_t show_frequency_list(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	int i;
+	ssize_t count = 0;
+
+	for (i = 0; i < sfd.freq_cnt; i++)
+		count += sprintf(&buf[count], "%lu ", sfd.freq_list[i]);
+	count += sprintf(&buf[count], "\n");
+
+	return count;
+}
+
+static ssize_t show_frequency_request(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	return sprintf(buf, "%lu\n", sfd.freq_request);
+}
+
+static ssize_t show_frequency_limit(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	return sprintf(buf, "%lu\n", sfd.freq_limit);
+}
+
+static ssize_t show_frequency(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	return sprintf(buf, "%lu\n", sfd.freq);
+}
+
+static ssize_t show_stat(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	return sprintf(buf, "gpu %lu %lu\n",
+		sfd.total_active_time, sfd.total_idle_time);
+}
+
+static ssize_t show_governor_list(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	ssize_t i = 0;
+	struct sgxfreq_governor *t;
+
+	list_for_each_entry(t, &sfd.gov_list, governor_list) {
+		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
+		    - (SGXFREQ_NAME_LEN + 2)))
+			goto out;
+		i += scnprintf(&buf[i], SGXFREQ_NAME_LEN, "%s ", t->name);
+	}
+out:
+	i += sprintf(&buf[i], "\n");
+	return i;
+}
+
+static ssize_t show_governor(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	if (sfd.gov)
+		return scnprintf(buf, SGXFREQ_NAME_LEN, "%s\n", sfd.gov->name);
+
+	return sprintf(buf, "\n");
+}
+
+static ssize_t store_governor(struct device *dev,
+			      struct device_attribute *attr, const char *buf,
+			      size_t count)
+{
+	int ret;
+	char name[16];
+
+	ret = sscanf(buf, "%15s", name);
+	if (ret != 1)
+		return -EINVAL;
+
+	ret = sgxfreq_set_governor(name);
+	if (ret)
+		return ret;
+	else
+		return count;
+}
+
+static DEVICE_ATTR(frequency_list, 0444, show_frequency_list, NULL);
+static DEVICE_ATTR(frequency_request, 0444, show_frequency_request, NULL);
+static DEVICE_ATTR(frequency_limit, 0444, show_frequency_limit, NULL);
+static DEVICE_ATTR(frequency, 0444, show_frequency, NULL);
+static DEVICE_ATTR(governor_list, 0444, show_governor_list, NULL);
+static DEVICE_ATTR(governor, 0644, show_governor, store_governor);
+static DEVICE_ATTR(stat, 0444, show_stat, NULL);
+
+static const struct attribute *sgxfreq_attributes[] = {
+	&dev_attr_frequency_list.attr,
+	&dev_attr_frequency_request.attr,
+	&dev_attr_frequency_limit.attr,
+	&dev_attr_frequency.attr,
+	&dev_attr_governor_list.attr,
+	&dev_attr_governor.attr,
+	&dev_attr_stat.attr,
+	NULL
+};
+
+/************************ end sysfs interface ************************/
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+static int set_volt_for_freq(unsigned long freq)
+{
+	struct opp *opp;
+	unsigned long volt = 0;
+	int ret;
+
+	if (sfd.gpu_reg) {
+		opp = opp_find_freq_exact(sfd.dev, freq, true);
+		if(IS_ERR(opp))
+		{
+			int r = PTR_ERR(opp);
+			pr_err("sgxfreq: Couldn't find opp matching freq: %lu. Err: %d",
+					freq, r);
+			return -1;
+		}
+
+		volt = opp_get_voltage(opp);
+		if (!volt)
+		{
+			pr_err("sgxfreq: Could find volt corresponding to freq: %lu\n",
+					freq);
+			return -1;
+		}
+
+		ret = regulator_set_voltage_tol(sfd.gpu_reg, volt , 6000);
+		if (ret) {
+			pr_err("sgxfreq: Error(%d) setting volt: %lu for freq:%lu\n",
+					ret, volt, freq);
+			return ret;
+		}
+	}
+
+	return 0;
+
+}
+#endif
+
+static int __set_freq(void)
+{
+	unsigned long freq;
+	int ret = 0;
+
+	freq = min(sfd.freq_request, sfd.freq_limit);
+	if (freq != sfd.freq) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+		if (freq > sfd.freq) {
+			/* Going up - must scale voltage before clocks */
+			if (set_volt_for_freq(freq) != 0) {
+				pr_err("sgxfreq: Error setting voltage for freq: %lu\n",
+						freq);
+				goto err1;
+			}
+		}
+#endif
+
+		ret = clk_set_rate(sfd.gpu_core_clk, freq);
+		if (ret) {
+			pr_err("sgxfreq: Error(%d) setting gpu core clock rate: %lu\n",
+					ret, freq);
+			goto err2;
+		}
+
+		ret = clk_set_rate(sfd.gpu_hyd_clk, freq);
+		if (ret) {
+			pr_err("sgxfreq: Error(%d) setting gpu hyd clock rate: %lu\n",
+					ret, freq);
+			goto err3;
+		}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+		if (freq < sfd.freq) {
+			/* Going down - must scale voltage after clocks */
+			if(set_volt_for_freq(freq) != 0) {
+				pr_err("sgxfreq: Error setting voltage for freq: %lu\n",
+						freq);
+				goto err4;
+			}
+		}
+#endif
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
+		sfd.pdata->device_scale(sfd.dev, sfd.dev, freq);
+#else
+		sfd.pdata->device_scale(sfd.dev, freq);
+#endif
+		sfd.freq = freq;
+
+		goto noerr;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+err4:
+#endif
+		ret |= clk_set_rate(sfd.gpu_hyd_clk, sfd.freq);
+
+err3:
+		ret |= clk_set_rate(sfd.gpu_core_clk, sfd.freq);
+err2:
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+		if(freq > sfd.freq)
+			ret |= set_volt_for_freq(sfd.freq);
+err1:
+#endif
+#endif
+noerr:
+		return ret;
+	}
+	return ret;
+}
+
+static struct sgxfreq_governor *__find_governor(const char *name)
+{
+        struct sgxfreq_governor *t;
+
+        list_for_each_entry(t, &sfd.gov_list, governor_list)
+                if (!strncasecmp(name, t->name, SGXFREQ_NAME_LEN))
+                        return t;
+
+        return NULL;
+}
+
+static void __update_timing_info(bool active)
+{
+	struct timeval tv;
+	do_gettimeofday(&tv);
+	if(active)
+	{
+		if(sfd.sgx_data.active == true) {
+			_active_curr_time = __tv2msec(tv);
+			sfd.total_active_time += __delta32(
+					_active_curr_time, _active_prev_time);
+			SGXFREQ_TRACE("A->A TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
+					sfd.total_active_time,
+					__delta32(_active_curr_time, _active_prev_time),
+					sfd.total_active_time,
+					(unsigned long)0);
+			_active_prev_time = _active_curr_time;
+		} else {
+			_idle_curr_time = __tv2msec(tv);
+			_active_prev_time = _idle_curr_time;
+			sfd.total_idle_time +=
+					__delta32(_idle_curr_time, _idle_prev_time);
+			SGXFREQ_TRACE("I->A TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
+					sfd.total_active_time,
+					(unsigned long)0,
+					sfd.total_idle_time,
+					__delta32(_idle_curr_time, _idle_prev_time));
+		}
+	} else {
+		if(sfd.sgx_data.active == true)
+		{
+			_idle_prev_time = _active_curr_time = __tv2msec(tv);
+			sfd.total_active_time +=
+					__delta32(_active_curr_time, _active_prev_time);
+			SGXFREQ_TRACE("A->I TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
+					sfd.total_active_time,
+					__delta32(_active_curr_time, _active_prev_time),
+					sfd.total_active_time,
+					(unsigned long)0);
+		}
+		else
+		{
+			_idle_curr_time = __tv2msec(tv);
+			sfd.total_idle_time += __delta32(
+					_idle_curr_time, _idle_prev_time);
+			SGXFREQ_TRACE("I->I TA:= %lums \tdA: %lums \tTI: %lums \tdI: %lums\n",
+					sfd.total_active_time,
+					(unsigned long)0,
+					sfd.total_idle_time,
+					__delta32(_idle_curr_time, _idle_prev_time));
+			_idle_prev_time = _idle_curr_time;
+		}
+	}
+}
+
+int sgxfreq_init(struct device *dev)
+{
+	int i, ret;
+	unsigned long freq;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+	struct dev_pm_opp *opp;
+	struct device_node *np;
+	unsigned int voltage_latency;
+#else
+	struct opp *opp;
+#endif
+	struct timeval tv;
+
+	sfd.dev = dev;
+	if (!sfd.dev)
+		return -EINVAL;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
+	sfd.pdata = (struct gpu_platform_data *)dev->platform_data;
+	if (!sfd.pdata ||
+	    !sfd.pdata->opp_get_opp_count ||
+	    !sfd.pdata->opp_find_freq_ceil ||
+	    !sfd.pdata->device_scale)
+		return -EINVAL;
+#endif
+
+	rcu_read_lock();
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
+	sfd.freq_cnt = sfd.pdata->opp_get_opp_count(dev);
+#else
+        ret = of_init_opp_table(dev);
+        if (ret) {
+                pr_err("sgxfreq: failed to init OPP table: %d\n", ret);
+		return -EINVAL;
+        }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+	sfd.freq_cnt = opp_get_opp_count(dev);
+#else
+	sfd.freq_cnt = dev_pm_opp_get_opp_count(dev);
+#endif
+#endif
+	if (sfd.freq_cnt < 1) {
+		pr_err("sgxfreq: failed to get operating frequencies\n");
+		rcu_read_unlock();
+		return -ENODEV;
+	}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
+	np = of_node_get(dev->of_node);
+        sfd.clk_nb = of_pm_voltdm_notifier_register(dev, np, sfd.gpu_core_clk, "gpu",
+                                                &voltage_latency);
+
+        if (IS_ERR(sfd.clk_nb)) {
+                ret = PTR_ERR(sfd.clk_nb);
+                /* defer probe if regulator is not yet registered */
+                if (ret == -EPROBE_DEFER) {
+                        dev_err(dev,
+                                "gpu clock notifier not ready, retry\n");
+                } else {
+                        dev_err(dev,
+                                "Failed to register gpu clock notifier: %d\n",
+                                ret);
+                }
+		return ret;
+        }
+
+#endif
+	sfd.freq_list = kmalloc(sfd.freq_cnt * sizeof(unsigned long), GFP_ATOMIC);
+        if (!sfd.freq_list) {
+		rcu_read_unlock();
+		return -ENOMEM;
+	}
+
+	freq = 0;
+	for (i = 0; i < sfd.freq_cnt; i++) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
+		opp = sfd.pdata->opp_find_freq_ceil(dev, &freq);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+		opp = opp_find_freq_ceil(dev, &freq);
+#else
+		/* 3.14 and later kernels */
+		opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+#endif
+		if (IS_ERR_OR_NULL(opp)) {
+			rcu_read_unlock();
+			kfree(sfd.freq_list);
+			return -ENODEV;
+		}
+		sfd.freq_list[i] = freq;
+		freq++;
+	}
+	rcu_read_unlock();
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+	sfd.core_clk = devm_clk_get(dev, "dpll_core_h14x2_ck");
+	if (IS_ERR(sfd.core_clk)) {
+		ret = PTR_ERR(sfd.core_clk);
+		pr_err("sgxfreq: failed to get core clock: %d\n", ret);
+		return ret;
+	}
+
+	sfd.gpu_clk = devm_clk_get(dev, "dpll_gpu_m2_ck");
+	if (IS_ERR(sfd.gpu_clk)) {
+		ret = PTR_ERR(sfd.gpu_clk);
+		pr_err("sgxfreq: failed to get gpu clock: %d\n", ret);
+		return ret;
+	}
+
+	sfd.per_clk = devm_clk_get(dev, "dpll_per_h14x2_ck");
+	if (IS_ERR(sfd.per_clk)) {
+		ret = PTR_ERR(sfd.per_clk);
+		pr_err("sgxfreq: failed to get per clock: %d\n", ret);
+		return ret;
+	}
+
+	sfd.gpu_core_clk = devm_clk_get(dev, "gpu_core_gclk_mux");
+	if (IS_ERR(sfd.gpu_core_clk)) {
+		ret = PTR_ERR(sfd.gpu_core_clk);
+		pr_err("sgxfreq: failed to get gpu core clock: %d\n", ret);
+		return ret;
+	}
+
+	sfd.gpu_hyd_clk = devm_clk_get(dev, "gpu_core_gclk_mux");
+	if (IS_ERR(sfd.gpu_hyd_clk)) {
+		ret = PTR_ERR(sfd.gpu_hyd_clk);
+		pr_err("sgxfreq: failed to get gpu hyd clock: %d\n", ret);
+		return ret;
+	}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0))
+	sfd.gpu_reg = devm_regulator_get(dev, "gpu");
+	if (IS_ERR(sfd.gpu_reg)) {
+		if (PTR_ERR(sfd.gpu_reg) == -EPROBE_DEFER) {
+			dev_err(dev, "gpu regulator not ready, retry\n");
+			return -EPROBE_DEFER;
+		}
+		pr_err("sgxfreq: failed to get gpu regulator: %ld\n", PTR_ERR(sfd.gpu_reg));
+		sfd.gpu_reg = NULL;
+	}
+#endif
+
+	ret = clk_set_parent(sfd.gpu_hyd_clk, sfd.core_clk);
+	if (ret != 0) {
+		pr_err("sgxfreq: failed to set gpu_hyd_clk parent: %d\n", ret);
+	}
+
+	ret = clk_set_parent(sfd.gpu_core_clk, sfd.core_clk);
+	if (ret != 0) {
+		pr_err("sgxfreq: failed to set gpu_core_clk parent: %d\n", ret);
+	}
+#endif
+
+	mutex_init(&sfd.freq_mutex);
+	sfd.freq_limit = sfd.freq_list[sfd.freq_cnt - 1];
+	sgxfreq_set_freq_request(sfd.freq_list[sfd.freq_cnt - 1]);
+	sfd.sgx_data.clk_on = false;
+	sfd.sgx_data.active = false;
+
+	mutex_init(&sfd.gov_mutex);
+	INIT_LIST_HEAD(&sfd.gov_list);
+
+	sgxfreq_kobj = kobject_create_and_add("sgxfreq", &sfd.dev->kobj);
+	ret = sysfs_create_files(sgxfreq_kobj, sgxfreq_attributes);
+	if (ret) {
+		kfree(sfd.freq_list);
+		return ret;
+	}
+
+#if (defined(CONFIG_THERMAL) || defined(CONFIG_THERMAL_FRAMEWORK))
+	cool_init();
+#endif
+
+	for (i = 0; sgxfreq_gov_init[i] != NULL; i++)
+		sgxfreq_gov_init[i]();
+
+	if (sgxfreq_set_governor(SGXFREQ_DEFAULT_GOV_NAME)) {
+		kfree(sfd.freq_list);
+		return -ENODEV;
+	}
+	do_gettimeofday(&tv);
+	_idle_prev_time = _active_curr_time = _idle_curr_time =
+		_active_prev_time = __tv2msec(tv);
+
+	return 0;
+}
+
+int sgxfreq_deinit(void)
+{
+	int i;
+
+	sgxfreq_set_governor(NULL);
+
+	sgxfreq_set_freq_request(sfd.freq_list[0]);
+
+#if (defined(CONFIG_THERMAL) || defined(CONFIG_THERMAL_FRAMEWORK))
+	cool_deinit();
+#endif
+
+	for (i = 0; sgxfreq_gov_deinit[i] != NULL; i++)
+		sgxfreq_gov_deinit[i]();
+
+	sysfs_remove_files(sgxfreq_kobj, sgxfreq_attributes);
+	kobject_put(sgxfreq_kobj);
+
+	kfree(sfd.freq_list);
+
+	return 0;
+}
+
+int sgxfreq_register_governor(struct sgxfreq_governor *governor)
+{
+	if (!governor)
+		return -EINVAL;
+
+	list_add(&governor->governor_list, &sfd.gov_list);
+
+	return 0;
+}
+
+void sgxfreq_unregister_governor(struct sgxfreq_governor *governor)
+{
+	if (!governor)
+		return;
+
+	list_del(&governor->governor_list);
+}
+
+int sgxfreq_set_governor(const char *name)
+{
+	int ret = 0;
+	struct sgxfreq_governor *new_gov = 0;
+
+	if (name) {
+		new_gov = __find_governor(name);
+		if (!new_gov)
+			return -EINVAL;
+	}
+
+	mutex_lock(&sfd.gov_mutex);
+
+	if (sfd.gov && sfd.gov->gov_stop)
+		sfd.gov->gov_stop();
+
+	if (new_gov && new_gov->gov_start)
+		ret = new_gov->gov_start(&sfd.sgx_data);
+
+	if (ret) {
+		if (sfd.gov && sfd.gov->gov_start)
+			sfd.gov->gov_start(&sfd.sgx_data);
+		return -ENODEV;
+	}
+	sfd.gov = new_gov;
+
+	mutex_unlock(&sfd.gov_mutex);
+
+	return 0;
+}
+
+int sgxfreq_get_freq_list(unsigned long **pfreq_list)
+{
+	*pfreq_list = sfd.freq_list;
+
+	return sfd.freq_cnt;
+}
+
+unsigned long sgxfreq_get_freq_min(void)
+{
+	return sfd.freq_list[0];
+}
+
+unsigned long sgxfreq_get_freq_max(void)
+{
+	return sfd.freq_list[sfd.freq_cnt - 1];
+}
+
+unsigned long sgxfreq_get_freq_floor(unsigned long freq)
+{
+	int i;
+	unsigned long f = 0;
+
+	for (i = sfd.freq_cnt - 1; i >= 0; i--) {
+		f = sfd.freq_list[i];
+		if (f <= freq)
+			return f;
+	}
+
+	return f;
+}
+
+unsigned long sgxfreq_get_freq_ceil(unsigned long freq)
+{
+	int i;
+	unsigned long f = 0;
+
+	for (i = 0; i < sfd.freq_cnt; i++) {
+		f = sfd.freq_list[i];
+		if (f >= freq)
+			return f;
+	}
+
+	return f;
+}
+
+unsigned long sgxfreq_get_freq(void)
+{
+	return sfd.freq;
+}
+
+unsigned long sgxfreq_get_freq_request(void)
+{
+	return sfd.freq_request;
+}
+
+unsigned long sgxfreq_get_freq_limit(void)
+{
+	return sfd.freq_limit;
+}
+
+unsigned long sgxfreq_set_freq_request(unsigned long freq_request)
+{
+	freq_request = sgxfreq_get_freq_ceil(freq_request);
+
+	mutex_lock(&sfd.freq_mutex);
+
+	sfd.freq_request = freq_request;
+	__set_freq();
+
+	mutex_unlock(&sfd.freq_mutex);
+
+	return freq_request;
+}
+
+unsigned long sgxfreq_set_freq_limit(unsigned long freq_limit)
+{
+	freq_limit = sgxfreq_get_freq_ceil(freq_limit);
+
+	mutex_lock(&sfd.freq_mutex);
+
+	sfd.freq_limit = freq_limit;
+	__set_freq();
+
+	mutex_unlock(&sfd.freq_mutex);
+
+	return freq_limit;
+}
+
+unsigned long sgxfreq_get_total_active_time(void)
+{
+	__update_timing_info(sfd.sgx_data.active);
+	return sfd.total_active_time;
+}
+
+unsigned long sgxfreq_get_total_idle_time(void)
+{
+	__update_timing_info(sfd.sgx_data.active);
+	return sfd.total_idle_time;
+}
+
+/*
+ * sgx_clk_on, sgx_clk_off, sgx_active, and sgx_idle notifications are
+ * serialized by power lock. governor notif calls need sync with governor
+ * setting.
+ */
+void sgxfreq_notif_sgx_clk_on(void)
+{
+	sfd.sgx_data.clk_on = true;
+
+	mutex_lock(&sfd.gov_mutex);
+
+	if (sfd.gov && sfd.gov->sgx_clk_on)
+		sfd.gov->sgx_clk_on();
+
+	mutex_unlock(&sfd.gov_mutex);
+}
+
+void sgxfreq_notif_sgx_clk_off(void)
+{
+	sfd.sgx_data.clk_on = false;
+
+	mutex_lock(&sfd.gov_mutex);
+
+	if (sfd.gov && sfd.gov->sgx_clk_off)
+		sfd.gov->sgx_clk_off();
+
+	mutex_unlock(&sfd.gov_mutex);
+}
+
+
+void sgxfreq_notif_sgx_active(void)
+{
+	__update_timing_info(true);
+
+	sfd.sgx_data.active = true;
+
+	mutex_lock(&sfd.gov_mutex);
+
+	if (sfd.gov && sfd.gov->sgx_active)
+		sfd.gov->sgx_active();
+
+	mutex_unlock(&sfd.gov_mutex);
+
+}
+
+void sgxfreq_notif_sgx_idle(void)
+{
+
+	__update_timing_info(false);
+
+	sfd.sgx_data.active = false;
+
+	mutex_lock(&sfd.gov_mutex);
+
+	if (sfd.gov && sfd.gov->sgx_idle)
+		sfd.gov->sgx_idle();
+
+	mutex_unlock(&sfd.gov_mutex);
+}
+
+void sgxfreq_notif_sgx_frame_done(void)
+{
+	mutex_lock(&sfd.gov_mutex);
+
+	if (sfd.gov && sfd.gov->sgx_frame_done)
+		sfd.gov->sgx_frame_done();
+
+	mutex_unlock(&sfd.gov_mutex);
+}
diff --git a/drivers/gpu/pvr/services4/system/omap/sgxfreq.h b/drivers/gpu/pvr/services4/system/omap/sgxfreq.h
new file mode 100644
index 0000000..01ecf85
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sgxfreq.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc
+ *
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef SGXFREQ_H
+#define SGXFREQ_H
+
+#include <linux/device.h>
+#include <linux/time.h>
+
+#define SGXFREQ_NAME_LEN 16
+
+//#define SGXFREQ_DEBUG_FTRACE
+#if defined(SGXFREQ_DEBUG_FTRACE)
+#define SGXFREQ_TRACE(...) trace_printk(__VA_ARGS__)
+#else
+#define SGXFREQ_TRACE(...)
+#endif
+
+struct sgxfreq_sgx_data {
+	bool clk_on;
+	bool active;
+};
+
+struct sgxfreq_governor {
+	char name[SGXFREQ_NAME_LEN];
+	int (*gov_start) (struct sgxfreq_sgx_data *data);
+	void (*gov_stop) (void);
+	void (*sgx_clk_on) (void);
+	void (*sgx_clk_off) (void);
+	void (*sgx_active) (void);
+	void (*sgx_idle) (void);
+	void (*sgx_frame_done) (void);
+	struct list_head governor_list;
+};
+
+/* sgxfreq_init must be called before any other api */
+int sgxfreq_init(struct device *dev);
+int sgxfreq_deinit(void);
+
+int sgxfreq_register_governor(struct sgxfreq_governor *governor);
+void sgxfreq_unregister_governor(struct sgxfreq_governor *governor);
+
+int sgxfreq_set_governor(const char *name);
+
+int sgxfreq_get_freq_list(unsigned long **pfreq_list);
+
+unsigned long sgxfreq_get_freq_min(void);
+unsigned long sgxfreq_get_freq_max(void);
+
+unsigned long sgxfreq_get_freq_floor(unsigned long freq);
+unsigned long sgxfreq_get_freq_ceil(unsigned long freq);
+
+unsigned long sgxfreq_get_freq(void);
+unsigned long sgxfreq_get_freq_request(void);
+unsigned long sgxfreq_get_freq_limit(void);
+
+unsigned long sgxfreq_set_freq_request(unsigned long freq_request);
+unsigned long sgxfreq_set_freq_limit(unsigned long freq_limit);
+
+unsigned long sgxfreq_get_total_active_time(void);
+unsigned long sgxfreq_get_total_idle_time(void);
+
+/* Helper functions */
+static inline unsigned long __tv2msec(struct timeval tv)
+{
+	return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+}
+
+static inline unsigned long __delta32(unsigned long a, unsigned long b)
+{
+	if (a >= b)
+		return a - b;
+	else
+		return 1 + (0xFFFFFFFF - b) + a;
+}
+
+/* External notifications to sgxfreq */
+void sgxfreq_notif_sgx_clk_on(void);
+void sgxfreq_notif_sgx_clk_off(void);
+void sgxfreq_notif_sgx_active(void);
+void sgxfreq_notif_sgx_idle(void);
+void sgxfreq_notif_sgx_frame_done(void);
+
+#endif
diff --git a/drivers/gpu/pvr/services4/system/omap/sgxfreq_activeidle.c b/drivers/gpu/pvr/services4/system/omap/sgxfreq_activeidle.c
new file mode 100644
index 0000000..bb9b6c7
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sgxfreq_activeidle.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc
+ *
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <linux/sysfs.h>
+#include "sgxfreq.h"
+
+static int activeidle_start(struct sgxfreq_sgx_data *data);
+static void activeidle_stop(void);
+static void activeidle_sgx_active(void);
+static void activeidle_sgx_idle(void);
+
+static struct activeidle_data {
+	unsigned long freq_active;
+	unsigned long freq_idle;
+	struct mutex mutex;
+	bool sgx_active;
+} aid;
+
+static struct sgxfreq_governor activeidle_gov = {
+	.name =	"activeidle",
+	.gov_start = activeidle_start,
+	.gov_stop = activeidle_stop,
+	.sgx_active = activeidle_sgx_active,
+	.sgx_idle = activeidle_sgx_idle,
+};
+
+/*********************** begin sysfs interface ***********************/
+
+extern struct kobject *sgxfreq_kobj;
+
+static ssize_t show_freq_active(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return sprintf(buf, "%lu\n", aid.freq_active);
+}
+
+static ssize_t store_freq_active(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	int ret;
+	unsigned long freq;
+
+	ret = sscanf(buf, "%lu", &freq);
+	if (ret != 1)
+		return -EINVAL;
+
+	freq = sgxfreq_get_freq_ceil(freq);
+
+	mutex_lock(&aid.mutex);
+
+	aid.freq_active = freq;
+	if (aid.sgx_active)
+		sgxfreq_set_freq_request(aid.freq_active);
+
+	mutex_unlock(&aid.mutex);
+
+	return count;
+}
+
+static ssize_t show_freq_idle(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	return sprintf(buf, "%lu\n", aid.freq_idle);
+}
+
+static ssize_t store_freq_idle(struct device *dev, struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	int ret;
+	unsigned long freq;
+
+	ret = sscanf(buf, "%lu", &freq);
+	if (ret != 1)
+		return -EINVAL;
+
+	freq = sgxfreq_get_freq_floor(freq);
+
+	mutex_lock(&aid.mutex);
+
+	aid.freq_idle = freq;
+	if (!aid.sgx_active)
+		sgxfreq_set_freq_request(aid.freq_idle);
+
+	mutex_unlock(&aid.mutex);
+
+	return count;
+}
+static DEVICE_ATTR(freq_active, 0644, show_freq_active, store_freq_active);
+static DEVICE_ATTR(freq_idle, 0644, show_freq_idle, store_freq_idle);
+
+static struct attribute *activeidle_attributes[] = {
+	&dev_attr_freq_active.attr,
+	&dev_attr_freq_idle.attr,
+	NULL
+};
+
+static struct attribute_group activeidle_attr_group = {
+	.attrs = activeidle_attributes,
+	.name = "activeidle",
+};
+
+/************************ end sysfs interface ************************/
+
+int activeidle_init(void)
+{
+	int ret;
+
+	mutex_init(&aid.mutex);
+
+	ret = sgxfreq_register_governor(&activeidle_gov);
+	if (ret)
+		return ret;
+
+	aid.freq_idle = sgxfreq_get_freq_min();
+	aid.freq_active = sgxfreq_get_freq_max();
+
+	return 0;
+}
+
+int activeidle_deinit(void)
+{
+	return 0;
+}
+
+static int activeidle_start(struct sgxfreq_sgx_data *data)
+{
+	int ret;
+
+	aid.sgx_active = data->active;
+
+	ret = sysfs_create_group(sgxfreq_kobj, &activeidle_attr_group);
+	if (ret)
+		return ret;
+
+	if (aid.sgx_active)
+		sgxfreq_set_freq_request(aid.freq_active);
+	else
+		sgxfreq_set_freq_request(aid.freq_idle);
+
+	return 0;
+}
+
+static void activeidle_stop(void)
+{
+	sysfs_remove_group(sgxfreq_kobj, &activeidle_attr_group);
+}
+
+static void activeidle_sgx_active(void)
+{
+	mutex_lock(&aid.mutex);
+
+	aid.sgx_active = true;
+	sgxfreq_set_freq_request(aid.freq_active);
+
+	mutex_unlock(&aid.mutex);
+}
+
+static void activeidle_sgx_idle(void)
+{
+	mutex_lock(&aid.mutex);
+
+	aid.sgx_active = false;
+	sgxfreq_set_freq_request(aid.freq_idle);
+
+	mutex_unlock(&aid.mutex);
+}
diff --git a/drivers/gpu/pvr/services4/system/omap/sgxfreq_cool.c b/drivers/gpu/pvr/services4/system/omap/sgxfreq_cool.c
new file mode 100644
index 0000000..0940362
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sgxfreq_cool.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc
+ *
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+
+#include <linux/thermal.h>
+
+static struct cool_data {
+	int freq_cnt;
+	unsigned long *freq_list;
+	unsigned long state;
+	struct thermal_cooling_device *cdev;
+} cd;
+
+static int sgxfreq_get_max_state(struct thermal_cooling_device *cdev,
+		unsigned long *state)
+{
+	*state = cd.freq_cnt - 1;
+	return 0;
+}
+
+static int sgxfreq_get_cur_state(struct thermal_cooling_device *cdev,
+		unsigned long *state)
+{
+	*state = cd.state;
+	return 0;
+}
+
+static int sgxfreq_set_cur_state(struct thermal_cooling_device *cdev,
+		unsigned long state)
+{
+	int freq_max_index, freq_limit_index;
+
+	freq_max_index = cd.freq_cnt - 1;
+
+	freq_limit_index = freq_max_index - (unsigned int)state;
+
+	if (freq_limit_index < 0)
+		freq_limit_index = 0;
+
+	sgxfreq_set_freq_limit(cd.freq_list[freq_limit_index]);
+
+	cd.state = state;
+	return 0;
+}
+
+
+static const struct thermal_cooling_device_ops sgxfreq_cooling_ops = {
+	.get_max_state = sgxfreq_get_max_state,
+	.get_cur_state = sgxfreq_get_cur_state,
+	.set_cur_state = sgxfreq_set_cur_state,
+};
+
+int cool_init(void)
+{
+	int ret;
+	struct thermal_zone_device *tz;
+
+	cd.freq_cnt = sgxfreq_get_freq_list(&cd.freq_list);
+	if (!cd.freq_cnt || !cd.freq_list)
+		return -EINVAL;
+
+	cd.cdev = thermal_cooling_device_register("gpu", (void *)NULL, &sgxfreq_cooling_ops);
+
+	if(IS_ERR(cd.cdev)) {
+		pr_err("sgxfreq: Error while regeistering cooling device: %ld\n", PTR_ERR(cd.cdev));
+		return -1;
+	}
+
+	tz = thermal_zone_get_zone_by_name("gpu");
+	if(IS_ERR(tz)) {
+		pr_err("sgxfreq: Error while trying to obtain zone device: %ld\n", PTR_ERR(tz));
+		return -1;
+	}
+
+	ret = thermal_zone_bind_cooling_device(tz, 0, cd.cdev, THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+	if (ret)
+	{
+		pr_err("sgxfreq: Error binding cooling device: %d\n", ret);
+	}
+
+	return 0;
+}
+
+void cool_deinit(void)
+{
+	thermal_cooling_device_unregister(cd.cdev);
+}
+#else //if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+#include <linux/thermal_framework.h>
+
+static int cool_device(struct thermal_dev *dev, int cooling_level);
+
+static struct cool_data {
+	int freq_cnt;
+	unsigned long *freq_list;
+} cd;
+
+static struct thermal_dev_ops cool_dev_ops = {
+	.cool_device = cool_device,
+};
+
+static struct thermal_dev cool_dev = {
+	.name = "gpu_cooling.0",
+	.domain_name = "gpu",
+	.dev_ops = &cool_dev_ops,
+};
+
+static struct thermal_dev case_cool_dev = {
+	.name = "gpu_cooling.1",
+	.domain_name = "case",
+	.dev_ops = &cool_dev_ops,
+};
+
+static unsigned int gpu_cooling_level;
+#if defined(CONFIG_CASE_TEMP_GOVERNOR)
+static unsigned int case_cooling_level;
+#endif
+
+int cool_init(void)
+{
+	int ret;
+	cd.freq_cnt = sgxfreq_get_freq_list(&cd.freq_list);
+	if (!cd.freq_cnt || !cd.freq_list)
+		return -EINVAL;
+
+	ret = thermal_cooling_dev_register(&cool_dev);
+	if (ret)
+		return ret;
+
+	return thermal_cooling_dev_register(&case_cool_dev);
+}
+
+void cool_deinit(void)
+{
+	thermal_cooling_dev_unregister(&cool_dev);
+	thermal_cooling_dev_unregister(&case_cool_dev);
+}
+
+static int cool_device(struct thermal_dev *dev, int cooling_level)
+{
+	int freq_max_index, freq_limit_index;
+
+#if defined(CONFIG_CASE_TEMP_GOVERNOR)
+	if (!strcmp(dev->domain_name, "case"))
+	{
+		int tmp = 0;
+		tmp = cooling_level - case_subzone_number;
+		if (tmp < 0)
+			tmp = 0;
+		case_cooling_level = tmp;
+	}
+	else
+#endif
+	{
+               gpu_cooling_level = cooling_level;
+	}
+
+	freq_max_index = cd.freq_cnt - 1;
+#if defined(CONFIG_CASE_TEMP_GOVERNOR)
+	if (case_cooling_level > gpu_cooling_level)
+	{
+		freq_limit_index = freq_max_index - case_cooling_level;
+	}
+	else
+#endif
+	{
+		freq_limit_index = freq_max_index - gpu_cooling_level;
+	}
+
+	if (freq_limit_index < 0)
+		freq_limit_index = 0;
+
+	sgxfreq_set_freq_limit(cd.freq_list[freq_limit_index]);
+
+	return 0;
+}
+#endif //if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
diff --git a/drivers/gpu/pvr/services4/system/omap/sgxfreq_on3demand.c b/drivers/gpu/pvr/services4/system/omap/sgxfreq_on3demand.c
new file mode 100644
index 0000000..73a8b77
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sgxfreq_on3demand.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc
+ *
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <linux/sysfs.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include "sgxfreq.h"
+
+static int on3demand_start(struct sgxfreq_sgx_data *data);
+static void on3demand_stop(void);
+static void on3demand_predict(void);
+
+
+static struct sgxfreq_governor on3demand_gov = {
+	.name =	"on3demand",
+	.gov_start = on3demand_start,
+	.gov_stop = on3demand_stop,
+	.sgx_frame_done = on3demand_predict
+};
+
+static struct on3demand_data {
+	unsigned int load;
+	unsigned int up_threshold;
+	unsigned int down_threshold;
+	unsigned int history_size;
+	unsigned long prev_total_idle;
+	unsigned long prev_total_active;
+	unsigned int low_load_cnt;
+	struct mutex mutex;
+} odd;
+
+#define ON3DEMAND_DEFAULT_UP_THRESHOLD			80
+#define ON3DEMAND_DEFAULT_DOWN_THRESHOLD		30
+#define ON3DEMAND_DEFAULT_HISTORY_SIZE_THRESHOLD	5
+
+/*FIXME: This should be dynamic and queried from platform */
+#define ON3DEMAND_FRAME_DONE_DEADLINE_MS 16
+
+
+/*********************** begin sysfs interface ***********************/
+
+extern struct kobject *sgxfreq_kobj;
+
+static ssize_t show_down_threshold(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", odd.down_threshold);
+}
+
+static ssize_t store_down_threshold(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	unsigned int thres;
+
+	ret = sscanf(buf, "%u", &thres);
+	if (ret != 1)
+		return -EINVAL;
+
+	mutex_lock(&odd.mutex);
+
+	if (thres <= 100) {
+		odd.down_threshold = thres;
+		odd.low_load_cnt = 0;
+	} else {
+		return -EINVAL;
+	}
+
+	mutex_unlock(&odd.mutex);
+
+	return count;
+}
+
+static ssize_t show_up_threshold(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", odd.up_threshold);
+}
+
+static ssize_t store_up_threshold(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	unsigned int thres;
+
+	ret = sscanf(buf, "%u", &thres);
+	if (ret != 1)
+		return -EINVAL;
+
+	mutex_lock(&odd.mutex);
+
+	if (thres <= 100) {
+		odd.up_threshold = thres;
+		odd.low_load_cnt = 0;
+	} else {
+		return -EINVAL;
+	}
+
+	mutex_unlock(&odd.mutex);
+
+	return count;
+}
+
+static ssize_t show_history_size(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", odd.history_size);
+}
+
+static ssize_t store_history_size(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	unsigned int size;
+
+	ret = sscanf(buf, "%u", &size);
+	if (ret != 1)
+		return -EINVAL;
+
+	mutex_lock(&odd.mutex);
+
+	if (size >= 1) {
+		odd.history_size = size;
+		odd.low_load_cnt = 0;
+	} else {
+		return -EINVAL;
+	}
+
+	mutex_unlock(&odd.mutex);
+
+	return count;
+}
+
+static ssize_t show_load(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", odd.load);
+}
+
+static DEVICE_ATTR(down_threshold, 0644,
+	show_down_threshold, store_down_threshold);
+static DEVICE_ATTR(up_threshold, 0644,
+	show_up_threshold, store_up_threshold);
+static DEVICE_ATTR(history_size, 0644,
+	show_history_size, store_history_size);
+static DEVICE_ATTR(load, 0444,
+	show_load, NULL);
+
+static struct attribute *on3demand_attributes[] = {
+	&dev_attr_down_threshold.attr,
+	&dev_attr_up_threshold.attr,
+	&dev_attr_history_size.attr,
+	&dev_attr_load.attr,
+	NULL
+};
+
+static struct attribute_group on3demand_attr_group = {
+	.attrs = on3demand_attributes,
+	.name = "on3demand",
+};
+/************************ end sysfs interface ************************/
+
+int on3demand_init(void)
+{
+	int ret;
+
+	mutex_init(&odd.mutex);
+
+	ret = sgxfreq_register_governor(&on3demand_gov);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int on3demand_deinit(void)
+{
+	return 0;
+}
+
+static int on3demand_start(struct sgxfreq_sgx_data *data)
+{
+	int ret;
+
+	odd.load = 0;
+	odd.up_threshold = ON3DEMAND_DEFAULT_UP_THRESHOLD;
+	odd.down_threshold = ON3DEMAND_DEFAULT_DOWN_THRESHOLD;
+	odd.history_size = ON3DEMAND_DEFAULT_HISTORY_SIZE_THRESHOLD;
+	odd.prev_total_active = 0;
+	odd.prev_total_idle = 0;
+	odd.low_load_cnt = 0;
+
+	ret = sysfs_create_group(sgxfreq_kobj, &on3demand_attr_group);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void on3demand_stop(void)
+{
+	sysfs_remove_group(sgxfreq_kobj, &on3demand_attr_group);
+}
+
+static void on3demand_predict(void)
+{
+	static unsigned short first_sample = 1;
+	unsigned long total_active, delta_active;
+	unsigned long total_idle, delta_idle;
+	unsigned long freq;
+
+	if (first_sample == 1) {
+		first_sample = 0;
+		odd.prev_total_active = sgxfreq_get_total_active_time();
+		odd.prev_total_idle = sgxfreq_get_total_idle_time();
+		return;
+	}
+
+	/* Sample new active and idle times */
+	total_active = sgxfreq_get_total_active_time();
+	total_idle = sgxfreq_get_total_idle_time();
+
+	/* Compute load */
+	delta_active = __delta32(total_active, odd.prev_total_active);
+	delta_idle = __delta32(total_idle, odd.prev_total_idle);
+
+	/*
+	 * If SGX was active for longer than frame display time (1/fps),
+	 * scale to highest possible frequency.
+	 */
+	if (delta_active > ON3DEMAND_FRAME_DONE_DEADLINE_MS) {
+		odd.low_load_cnt = 0;
+		sgxfreq_set_freq_request(sgxfreq_get_freq_max());
+	}
+
+	if ((delta_active + delta_idle))
+		odd.load = (100 * delta_active / (delta_active + delta_idle));
+	odd.prev_total_active = total_active;
+	odd.prev_total_idle = total_idle;
+
+	/* Scale GPU frequency on purpose */
+	if (odd.load >= odd.up_threshold) {
+		odd.low_load_cnt = 0;
+		sgxfreq_set_freq_request(sgxfreq_get_freq_max());
+	} else if (odd.load <= odd.down_threshold) {
+		if (odd.low_load_cnt == odd.history_size) {
+			/* Convert load to frequency */
+			freq = (sgxfreq_get_freq() * odd.load) / 100;
+			sgxfreq_set_freq_request(freq);
+			odd.low_load_cnt = 0;
+		} else {
+			odd.low_load_cnt++;
+		}
+	} else {
+		odd.low_load_cnt = 0;
+	}
+}
diff --git a/drivers/gpu/pvr/services4/system/omap/sgxfreq_onoff.c b/drivers/gpu/pvr/services4/system/omap/sgxfreq_onoff.c
new file mode 100644
index 0000000..40f33dd
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sgxfreq_onoff.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc
+ *
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <linux/sysfs.h>
+#include "sgxfreq.h"
+
+static int onoff_start(struct sgxfreq_sgx_data *data);
+static void onoff_stop(void);
+static void onoff_sgx_clk_on(void);
+static void onoff_sgx_clk_off(void);
+
+static struct onoff_data {
+	unsigned long freq_off;
+	unsigned long freq_on;
+	struct mutex mutex;
+	bool sgx_clk_on;
+} ood;
+
+static struct sgxfreq_governor onoff_gov = {
+	.name =	"onoff",
+	.gov_start = onoff_start,
+	.gov_stop = onoff_stop,
+	.sgx_clk_on = onoff_sgx_clk_on,
+	.sgx_clk_off = onoff_sgx_clk_off,
+};
+
+/*********************** begin sysfs interface ***********************/
+
+extern struct kobject *sgxfreq_kobj;
+
+static ssize_t show_freq_on(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	return sprintf(buf, "%lu\n", ood.freq_on);
+}
+
+static ssize_t store_freq_on(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	int ret;
+	unsigned long freq;
+
+	ret = sscanf(buf, "%lu", &freq);
+	if (ret != 1)
+		return -EINVAL;
+
+	freq = sgxfreq_get_freq_ceil(freq);
+
+	mutex_lock(&ood.mutex);
+
+	ood.freq_on = freq;
+	if (ood.sgx_clk_on)
+		sgxfreq_set_freq_request(ood.freq_on);
+
+	mutex_unlock(&ood.mutex);
+
+	return count;
+}
+
+static ssize_t show_freq_off(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	return sprintf(buf, "%lu\n", ood.freq_off);
+}
+
+static ssize_t store_freq_off(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	int ret;
+	unsigned long freq;
+
+	ret = sscanf(buf, "%lu", &freq);
+	if (ret != 1)
+		return -EINVAL;
+
+	freq = sgxfreq_get_freq_floor(freq);
+
+	mutex_lock(&ood.mutex);
+
+	ood.freq_off = freq;
+	if (!ood.sgx_clk_on)
+		sgxfreq_set_freq_request(ood.freq_off);
+
+	mutex_unlock(&ood.mutex);
+
+	return count;
+}
+static DEVICE_ATTR(freq_on, 0644, show_freq_on, store_freq_on);
+static DEVICE_ATTR(freq_off, 0644, show_freq_off, store_freq_off);
+
+static struct attribute *onoff_attributes[] = {
+	&dev_attr_freq_on.attr,
+	&dev_attr_freq_off.attr,
+	NULL
+};
+
+static struct attribute_group onoff_attr_group = {
+	.attrs = onoff_attributes,
+	.name = "onoff",
+};
+
+/************************ end sysfs interface ************************/
+
+int onoff_init(void)
+{
+	int ret;
+
+	mutex_init(&ood.mutex);
+
+	ret = sgxfreq_register_governor(&onoff_gov);
+	if (ret)
+		return ret;
+
+	ood.freq_off = sgxfreq_get_freq_min();
+	ood.freq_on = sgxfreq_get_freq_max();
+
+	return 0;
+}
+
+int onoff_deinit(void)
+{
+	return 0;
+}
+
+static int onoff_start(struct sgxfreq_sgx_data *data)
+{
+	int ret;
+
+	ood.sgx_clk_on = data->clk_on;
+
+	ret = sysfs_create_group(sgxfreq_kobj, &onoff_attr_group);
+	if (ret)
+		return ret;
+
+	if (ood.sgx_clk_on)
+		sgxfreq_set_freq_request(ood.freq_on);
+	else
+		sgxfreq_set_freq_request(ood.freq_off);
+
+	return 0;
+}
+
+static void onoff_stop(void)
+{
+	sysfs_remove_group(sgxfreq_kobj, &onoff_attr_group);
+}
+
+static void onoff_sgx_clk_on(void)
+{
+	mutex_lock(&ood.mutex);
+
+	ood.sgx_clk_on = true;
+	sgxfreq_set_freq_request(ood.freq_on);
+
+	mutex_unlock(&ood.mutex);
+}
+
+static void onoff_sgx_clk_off(void)
+{
+	mutex_lock(&ood.mutex);
+
+	ood.sgx_clk_on = false;
+	sgxfreq_set_freq_request(ood.freq_off);
+
+	mutex_unlock(&ood.mutex);
+}
+
diff --git a/drivers/gpu/pvr/services4/system/omap/sgxfreq_userspace.c b/drivers/gpu/pvr/services4/system/omap/sgxfreq_userspace.c
new file mode 100644
index 0000000..c7c9aec
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sgxfreq_userspace.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2012 Texas Instruments, Inc
+ *
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <linux/sysfs.h>
+#include "sgxfreq.h"
+
+
+static int userspace_start(struct sgxfreq_sgx_data *data);
+static void userspace_stop(void);
+
+
+static struct sgxfreq_governor userspace_gov = {
+	.name =	"userspace",
+	.gov_start = userspace_start,
+	.gov_stop = userspace_stop,
+};
+
+
+static struct userspace_data {
+	unsigned long freq_user; /* in Hz */
+} usd;
+
+
+/*********************** begin sysfs interface ***********************/
+
+extern struct kobject *sgxfreq_kobj;
+
+
+static ssize_t show_frequency_set(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	return sprintf(buf, "%lu\n", usd.freq_user);
+}
+
+
+static ssize_t store_frequency_set(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	unsigned long freq;
+
+	ret = sscanf(buf, "%lu", &freq);
+	if (ret != 1)
+		return -EINVAL;
+
+	if (freq > sgxfreq_get_freq_max())
+		freq = sgxfreq_get_freq_max();
+	usd.freq_user = sgxfreq_set_freq_request(freq);
+	trace_printk("USERSPACE: new freq=%luHz.\n", usd.freq_user);
+
+	return count;
+}
+
+
+static DEVICE_ATTR(frequency_set, 0644,
+	show_frequency_set, store_frequency_set);
+
+
+static struct attribute *userspace_attributes[] = {
+	&dev_attr_frequency_set.attr,
+	NULL
+};
+
+
+static struct attribute_group userspace_attr_group = {
+	.attrs = userspace_attributes,
+	.name = "userspace",
+};
+
+/************************ end sysfs interface ************************/
+
+
+int userspace_init(void)
+{
+	int ret;
+
+	ret = sgxfreq_register_governor(&userspace_gov);
+	if (ret)
+		return ret;
+	return 0;
+}
+
+
+int userspace_deinit(void)
+{
+	return 0;
+}
+
+
+static int userspace_start(struct sgxfreq_sgx_data *data)
+{
+	int ret;
+
+	usd.freq_user = sgxfreq_get_freq();
+
+	ret = sysfs_create_group(sgxfreq_kobj, &userspace_attr_group);
+	if (ret)
+		return ret;
+
+	trace_printk("USERSPACE: started.\n");
+
+	return 0;
+}
+
+
+static void userspace_stop(void)
+{
+	sysfs_remove_group(sgxfreq_kobj, &userspace_attr_group);
+
+	trace_printk("USERSPACE: stopped.\n");
+}
diff --git a/drivers/gpu/pvr/services4/system/omap/sysconfig.c b/drivers/gpu/pvr/services4/system/omap/sysconfig.c
new file mode 100644
index 0000000..3ebb7c8
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sysconfig.c
@@ -0,0 +1,1267 @@
+/*************************************************************************/ /*!
+@Title          System Configuration
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    System Configuration functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#include "sysconfig.h"
+#include "services_headers.h"
+#include "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "syslocal.h"
+
+#include "ocpdefs.h"
+
+/* top level system data anchor point*/
+SYS_DATA* gpsSysData = (SYS_DATA*)IMG_NULL;
+SYS_DATA  gsSysData;
+
+static SYS_SPECIFIC_DATA gsSysSpecificData;
+SYS_SPECIFIC_DATA *gpsSysSpecificData;
+
+/* SGX structures */
+static IMG_UINT32			gui32SGXDeviceID;
+static SGX_DEVICE_MAP		gsSGXDeviceMap;
+static PVRSRV_DEVICE_NODE	*gpsSGXDevNode;
+
+
+#if defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED)
+static IMG_CPU_VIRTADDR gsSGXRegsCPUVAddr;
+#endif
+
+#if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO)
+extern struct platform_device *gpsPVRLDMDev;
+#endif
+
+IMG_UINT32 PVRSRV_BridgeDispatchKM(IMG_UINT32	Ioctl,
+								   IMG_BYTE		*pInBuf,
+								   IMG_UINT32	InBufLen,
+								   IMG_BYTE		*pOutBuf,
+								   IMG_UINT32	OutBufLen,
+								   IMG_UINT32	*pdwBytesTransferred);
+
+#if defined(SGX_OCP_REGS_ENABLED)
+
+static IMG_CPU_VIRTADDR gpvOCPRegsLinAddr;
+
+static PVRSRV_ERROR EnableSGXClocksWrap(SYS_DATA *psSysData)
+{
+	PVRSRV_ERROR eError = EnableSGXClocks(psSysData);
+
+#if !defined(SGX_OCP_NO_INT_BYPASS)
+	if(eError == PVRSRV_OK)
+	{
+		OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_SYSCONFIG, 0x14);
+		OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_DEBUG_CONFIG, EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_MASK);
+	}
+#endif
+	return eError;
+}
+
+#else /* defined(SGX_OCP_REGS_ENABLED) */
+
+static INLINE PVRSRV_ERROR EnableSGXClocksWrap(SYS_DATA *psSysData)
+{
+	return EnableSGXClocks(psSysData);
+}
+
+#endif /* defined(SGX_OCP_REGS_ENABLED) */
+
+static INLINE PVRSRV_ERROR EnableSystemClocksWrap(SYS_DATA *psSysData)
+{
+	PVRSRV_ERROR eError = EnableSystemClocks(psSysData);
+
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	if(eError == PVRSRV_OK)
+	{
+		/*
+		 * The SGX Clocks are enabled separately if active power
+		 * management is enabled.
+		 */
+		eError = EnableSGXClocksWrap(psSysData);
+		if (eError != PVRSRV_OK)
+		{
+			DisableSystemClocks(psSysData);
+		}
+	}
+#endif
+
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function	SysLocateDevices
+
+ @Description	Specifies devices in the systems memory map
+
+ @Input		psSysData - sys data
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData)
+{
+#if defined(NO_HARDWARE)
+	PVRSRV_ERROR eError;
+	IMG_CPU_PHYADDR sCpuPAddr;
+#else
+#if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO)
+	struct resource *dev_res;
+	int dev_irq;
+#endif
+#endif
+
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+
+	/* SGX Device: */
+	gsSGXDeviceMap.ui32Flags = 0x0;
+	
+#if defined(NO_HARDWARE)
+	/* 
+	 * For no hardware, allocate some contiguous memory for the
+	 * register block.
+	 */
+
+	/* Registers */
+	gsSGXDeviceMap.ui32RegsSize = SYS_OMAP_SGX_REGS_SIZE;
+
+	eError = OSBaseAllocContigMemory(gsSGXDeviceMap.ui32RegsSize,
+									 &gsSGXRegsCPUVAddr,
+									 &sCpuPAddr);
+	if(eError != PVRSRV_OK)
+	{
+		return eError;
+	}
+	gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr;
+	gsSGXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase);
+#if defined(__linux__)
+	/* Indicate the registers are already mapped */
+	gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+#else
+	/*
+	 * FIXME: Could we just use the virtual address returned by
+	 * OSBaseAllocContigMemory?
+	 */
+	gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL;
+#endif
+
+	OSMemSet(gsSGXRegsCPUVAddr, 0, gsSGXDeviceMap.ui32RegsSize);
+
+	/*
+		device interrupt IRQ
+		Note: no interrupts available on no hardware system
+	*/
+	gsSGXDeviceMap.ui32IRQ = 0;
+
+#else /* defined(NO_HARDWARE) */
+#if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO)
+	/* get the resource and IRQ through platform resource API */
+	dev_res = platform_get_resource(gpsPVRLDMDev, IORESOURCE_MEM, 0);
+	if (dev_res == NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_resource failed", __FUNCTION__));
+		return PVRSRV_ERROR_INVALID_DEVICE;
+	}
+
+	dev_irq = platform_get_irq(gpsPVRLDMDev, 0);
+	if (dev_irq < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_irq failed (%d)", __FUNCTION__, -dev_irq));
+		return PVRSRV_ERROR_INVALID_DEVICE;
+	}
+	
+	gsSGXDeviceMap.sRegsSysPBase.uiAddr = dev_res->start;
+	gsSGXDeviceMap.sRegsCpuPBase =
+		SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+	PVR_TRACE(("SGX register base: 0x%lx", (unsigned long)gsSGXDeviceMap.sRegsCpuPBase.uiAddr));
+
+#if defined(SGX544) && defined(SGX_FEATURE_MP)
+	/* FIXME: Workaround due to HWMOD change. Otherwise this region is too small. */
+	gsSGXDeviceMap.ui32RegsSize = SYS_OMAP_SGX_REGS_SIZE;
+#else
+	gsSGXDeviceMap.ui32RegsSize = (unsigned int)(dev_res->end - dev_res->start);
+#endif
+	PVR_TRACE(("SGX register size: %d",gsSGXDeviceMap.ui32RegsSize));
+
+	gsSGXDeviceMap.ui32IRQ = dev_irq;
+	PVR_TRACE(("SGX IRQ: %d", gsSGXDeviceMap.ui32IRQ));
+#else	/* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */
+	gsSGXDeviceMap.sRegsSysPBase.uiAddr = SYS_OMAP_SGX_REGS_SYS_PHYS_BASE;
+	gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+	gsSGXDeviceMap.ui32RegsSize = SYS_OMAP_SGX_REGS_SIZE;
+
+	gsSGXDeviceMap.ui32IRQ = SYS_OMAP_SGX_IRQ;
+
+#endif	/* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */
+#if defined(SGX_OCP_REGS_ENABLED)
+	gsSGXRegsCPUVAddr = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+	gsSGXDeviceMap.ui32RegsSize,
+											 PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY,
+											 IMG_NULL);
+
+	if (gsSGXRegsCPUVAddr == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Failed to map SGX registers"));
+		return PVRSRV_ERROR_BAD_MAPPING;
+	}
+
+	/* Indicate the registers are already mapped */
+	gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+	gpvOCPRegsLinAddr = gsSGXRegsCPUVAddr;
+#endif
+#endif /* defined(NO_HARDWARE) */
+
+#if defined(PDUMP)
+	{
+		/* initialise memory region name for pdumping */
+		static IMG_CHAR pszPDumpDevName[] = "SGXMEM";
+		gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName;
+	}
+#endif
+
+	/* add other devices here: */
+
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysCreateVersionString
+
+ @Description Read the version string 
+
+ @Return   IMG_CHAR *  : Version string
+
+******************************************************************************/
+static IMG_CHAR *SysCreateVersionString(void)
+{
+	static IMG_CHAR aszVersionString[100];
+	IMG_UINT32 ui32MaxStrLen;
+	SYS_DATA	*psSysData;
+	IMG_UINT32	ui32SGXRevision;
+	IMG_INT32	i32Count;
+
+	SysAcquireData(&psSysData);
+
+	ui32SGXRevision = SGX_CORE_REV;
+	ui32MaxStrLen = 99;
+
+	i32Count = OSSNPrintf(aszVersionString, ui32MaxStrLen + 1,
+			"SGX revision = %u",
+			(IMG_UINT)(ui32SGXRevision));
+	if(i32Count == -1)
+	{
+		return IMG_NULL;
+	}
+
+	return aszVersionString;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysInitialise
+ 
+ @Description Initialises kernel services at 'driver load' time
+ 
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR SysInitialise(IMG_VOID)
+{
+	IMG_UINT32			i;
+	PVRSRV_ERROR 		eError;
+	PVRSRV_DEVICE_NODE	*psDeviceNode;
+#if !defined(PVR_NO_OMAP_TIMER)
+	IMG_CPU_PHYADDR		TimerRegPhysBase;
+#endif
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+	SGX_TIMING_INFORMATION*	psTimingInfo;
+#endif
+	gpsSysData = &gsSysData;
+	OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+	gpsSysSpecificData =  &gsSysSpecificData;
+	OSMemSet(gpsSysSpecificData, 0, sizeof(SYS_SPECIFIC_DATA));
+
+	gpsSysData->pvSysSpecificData = gpsSysSpecificData;
+
+	eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure"));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA);
+
+	gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
+
+	/* init device ID's */
+	for(i=0; i<SYS_DEVICE_COUNT; i++)
+	{
+		gpsSysData->sDeviceID[i].uiID = i;
+		gpsSysData->sDeviceID[i].bInUse = IMG_FALSE;
+	}
+
+	gpsSysData->psDeviceNodeList = IMG_NULL;
+	gpsSysData->psQueueList = IMG_NULL;
+
+	eError = SysInitialiseCommon(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon"));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+	/* Set up timing information*/
+	psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
+	psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+	psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ; 
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	psTimingInfo->bEnableActivePM = IMG_TRUE;
+#else	
+	psTimingInfo->bEnableActivePM = IMG_FALSE;
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+	psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS; 
+	psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ; 
+#endif
+
+	/*
+		Setup the Source Clock Divider value
+	*/
+	gpsSysSpecificData->ui32SrcClockDiv = 3;
+
+	/*
+		Locate the devices within the system, specifying 
+		the physical addresses of each devices components 
+		(regs, mem, ports etc.)
+	*/
+	eError = SysLocateDevices(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices"));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV);
+
+	eError = SysPMRuntimeRegister();
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register with OSPM!"));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME);
+
+	eError = SysDvfsInitialize(gpsSysSpecificData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialize DVFS"));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_DVFS_INIT);
+
+	/*
+		Register devices with the system
+		This also sets up their memory maps/heaps
+	*/
+	eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice,
+								  DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_REGDEV);
+
+	/*
+		Once all devices are registered, specify the backing store
+		and, if required, customise the memory heap config
+	*/	
+	psDeviceNode = gpsSysData->psDeviceNodeList;
+	while(psDeviceNode)
+	{
+		/* perform any OEM SOC address space customisations here */
+		switch(psDeviceNode->sDevId.eDeviceType)
+		{
+			case PVRSRV_DEVICE_TYPE_SGX:
+			{
+				DEVICE_MEMORY_INFO *psDevMemoryInfo;
+				DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+				/* 
+					specify the backing store to use for the devices MMU PT/PDs
+					- the PT/PDs are always UMA in this system
+				*/
+				psDeviceNode->psLocalDevMemArena = IMG_NULL;
+
+				/* useful pointers */
+				psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+				psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+				/* specify the backing store for all SGX heaps */
+				for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+				{
+					psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+				}
+
+				gpsSGXDevNode = psDeviceNode;
+				gsSysSpecificData.psSGXDevNode = psDeviceNode;
+
+				break;
+			}
+			default:
+				PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!"));
+				return PVRSRV_ERROR_INIT_FAILURE;
+		}
+
+		/* advance to next device */
+		psDeviceNode = psDeviceNode->psNext;
+	}
+
+	eError = EnableSystemClocksWrap(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable system clocks (%d)", eError));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	eError = EnableSGXClocksWrap(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable SGX clocks (%d)", eError));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+#endif	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+	eError = PVRSRVInitialiseDevice(gui32SGXDeviceID);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+		(IMG_VOID)SysDeinitialise(gpsSysData);
+		gpsSysData = IMG_NULL;
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV);
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	/* SGX defaults to D3 power state */
+	DisableSGXClocks(gpsSysData);
+#endif	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+#if !defined(PVR_NO_OMAP_TIMER)
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+	TimerRegPhysBase = gsSysSpecificData.sTimerRegPhysBase;
+#else
+	TimerRegPhysBase.uiAddr = SYS_OMAP_GP11TIMER_REGS_SYS_PHYS_BASE;
+#endif
+	gpsSysData->pvSOCTimerRegisterKM = IMG_NULL;
+	gpsSysData->hSOCTimerRegisterOSMemHandle = 0;
+	if (TimerRegPhysBase.uiAddr != 0)
+	{
+		OSReservePhys(TimerRegPhysBase,
+				  4,
+				  PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+				  IMG_NULL,
+				  (IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM,
+				  &gpsSysData->hSOCTimerRegisterOSMemHandle);
+	}
+#endif /* !defined(PVR_NO_OMAP_TIMER) */
+
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysFinalise
+ 
+ @Description Final part of initialisation at 'driver load' time
+ 
+ @Return   PVRSRV_ERROR  : 
+
+******************************************************************************/
+PVRSRV_ERROR SysFinalise(IMG_VOID)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	eError = EnableSGXClocksWrap(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to Enable SGX clocks (%d)", eError));
+		return eError;
+	}
+#endif	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+	eError = OSInstallMISR(gpsSysData);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to install MISR"));
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR);
+
+#if defined(SYS_USING_INTERRUPTS)
+	/* install a Device ISR */
+	eError = OSInstallDeviceLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ, "SGX ISR", gpsSGXDevNode);
+	if (eError != PVRSRV_OK)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to install ISR"));
+		return eError;
+	}
+	SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR);
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	SysEnableSGXInterrupts(gpsSysData);
+#endif
+#endif /* defined(SYS_USING_INTERRUPTS) */
+#if defined(__linux__) || defined(__QNXNTO__)
+	/* Create a human readable version string for this system */
+	gpsSysData->pszVersionString = SysCreateVersionString();
+	if (!gpsSysData->pszVersionString)
+	{
+		PVR_DPF((PVR_DBG_ERROR,"SysFinalise: Failed to create a system version string"));
+	}
+	else
+	{
+		PVR_TRACE(("SysFinalise: Version string: %s", gpsSysData->pszVersionString));
+	}
+#endif
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	/* SGX defaults to D3 power state */
+	DisableSGXClocks(gpsSysData);
+#endif	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+	gpsSysSpecificData->bSGXInitComplete = IMG_TRUE;
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysDeinitialise
+
+ @Description	De-initialises kernel services at 'driver unload' time
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData)
+{
+	PVRSRV_ERROR eError;
+
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+
+	if(gpsSysData->pvSOCTimerRegisterKM)
+	{
+		OSUnReservePhys(gpsSysData->pvSOCTimerRegisterKM,
+						4,
+						PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED,
+						gpsSysData->hSOCTimerRegisterOSMemHandle);
+	}
+
+
+#if defined(SYS_USING_INTERRUPTS)
+	if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR))
+	{
+		eError = OSUninstallDeviceLISR(gpsSysData);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallDeviceLISR failed"));
+			return eError;
+		}
+	}
+#endif
+
+	if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR))
+	{
+		eError = OSUninstallMISR(gpsSysData);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed"));
+			return eError;
+		}
+	}
+
+	if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV))
+	{
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+		PVR_ASSERT(SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS));
+		/* Reenable SGX clocks whilst SGX is being deinitialised. */
+		eError = EnableSGXClocksWrap(gpsSysData);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: EnableSGXClocks failed"));
+			return eError;
+		}
+#endif	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+		/* Deinitialise SGX */
+		eError = PVRSRVDeinitialiseDevice(gui32SGXDeviceID);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+			return eError;
+		}
+	}
+
+	/* Disable system clocks. Must happen after last access to hardware */
+	if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS))
+	{
+		DisableSystemClocks(gpsSysData);
+	}
+
+	if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_DVFS_INIT))
+	{
+		eError = SysDvfsDeinitialize(gpsSysSpecificData);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: Failed to de-init DVFS"));
+			gpsSysData = IMG_NULL;
+			return eError;
+		}
+	}
+
+	if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME))
+	{
+		eError = SysPMRuntimeUnregister();
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: Failed to unregister with OSPM!"));
+			gpsSysData = IMG_NULL;
+			return eError;
+		}
+	}
+
+	if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA))
+	{	
+		eError = OSDeInitEnvData(gpsSysData->pvEnvSpecificData);
+		if (eError != PVRSRV_OK)
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init env structure"));
+			return eError;
+		}
+	}
+
+	SysDeinitialiseCommon(gpsSysData);
+
+#if defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED)
+	if(gsSGXRegsCPUVAddr != IMG_NULL)
+	{
+#if defined(NO_HARDWARE)
+		/* Free hardware resources. */
+		OSBaseFreeContigMemory(SYS_OMAP_SGX_REGS_SIZE, gsSGXRegsCPUVAddr, gsSGXDeviceMap.sRegsCpuPBase);
+#else
+#if defined(SGX_OCP_REGS_ENABLED)
+		OSUnMapPhysToLin(gsSGXRegsCPUVAddr,
+		gsSGXDeviceMap.ui32RegsSize,
+												 PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY,
+												 IMG_NULL);
+
+		gpvOCPRegsLinAddr = IMG_NULL;
+#endif
+#endif	/* defined(NO_HARDWARE) */
+		gsSGXRegsCPUVAddr = IMG_NULL;
+		gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+	}
+#endif	/* defined(NO_HARDWARE) || defined(SGX_OCP_REGS_ENABLED) */
+
+	
+	gpsSysSpecificData->ui32SysSpecificData = 0;
+	gpsSysSpecificData->bSGXInitComplete = IMG_FALSE;
+
+	gpsSysData = IMG_NULL;
+
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function		SysGetDeviceMemoryMap
+
+ @Description	returns a device address map for the specified device
+
+ @Input			eDeviceType - device type
+ @Input			ppvDeviceMap - void ptr to receive device specific info.
+
+ @Return		PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE	eDeviceType,
+								   IMG_VOID				**ppvDeviceMap)
+{
+
+	switch(eDeviceType)
+	{
+		case PVRSRV_DEVICE_TYPE_SGX:
+		{
+			/* just return a pointer to the structure */
+			*ppvDeviceMap = (IMG_VOID*)&gsSGXDeviceMap;
+
+			break;
+		}
+		default:
+		{
+			PVR_DPF((PVR_DBG_ERROR,"SysGetDeviceMemoryMap: unsupported device type"));
+		}
+	}
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+ @Function        SysCpuPAddrToDevPAddr
+
+ @Description     Compute a device physical address from a cpu physical
+                  address. Relevant when
+
+ @Input           cpu_paddr - cpu physical address.
+ @Input           eDeviceType - device type required if DevPAddr
+                                address spaces vary across devices
+                                in the same system
+ @Return         device physical address.
+
+******************************************************************************/
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE	eDeviceType,
+									  IMG_CPU_PHYADDR		CpuPAddr)
+{
+	IMG_DEV_PHYADDR DevPAddr;
+
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+	/* Note: for UMA system we assume DevP == CpuP */
+	DevPAddr.uiAddr = CpuPAddr.uiAddr;
+	
+	return DevPAddr;
+}
+
+/*!
+******************************************************************************
+ @Function        SysSysPAddrToCpuPAddr
+
+ @Description     Compute a cpu physical address from a system physical
+                  address.
+
+ @Input           sys_paddr - system physical address.
+ @Return          cpu physical address.
+
+******************************************************************************/
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR sys_paddr)
+{
+	IMG_CPU_PHYADDR cpu_paddr;
+
+	/* This would only be an inequality if the CPU's MMU did not point to
+	   sys address 0, ie. multi CPU system */
+	cpu_paddr.uiAddr = sys_paddr.uiAddr;
+	return cpu_paddr;
+}
+
+/*!
+******************************************************************************
+ @Function        SysCpuPAddrToSysPAddr
+
+ @Description     Compute a system physical address from a cpu physical
+	            address.
+
+ @Input           cpu_paddr - cpu physical address.
+ @Return          device physical address.
+
+******************************************************************************/
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr)
+{
+	IMG_SYS_PHYADDR sys_paddr;
+
+	/* This would only be an inequality if the CPU's MMU did not point to
+	   sys address 0, ie. multi CPU system */
+	sys_paddr.uiAddr = cpu_paddr.uiAddr;
+	return sys_paddr;
+}
+
+
+/*!
+******************************************************************************
+ @Function        SysSysPAddrToDevPAddr
+
+ @Description     Compute a device physical address from a system physical
+	            address.
+
+ @Input           SysPAddr - system physical address.
+ @Input           eDeviceType - device type required if DevPAddr 
+				address spaces vary across devices 
+				in the same system
+
+ @Return        Device physical address.
+
+******************************************************************************/
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr)
+{
+	IMG_DEV_PHYADDR DevPAddr;
+
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+	/* Note: for UMA system we assume DevP == CpuP */
+	DevPAddr.uiAddr = SysPAddr.uiAddr;
+
+	return DevPAddr;
+}
+
+
+/*!
+******************************************************************************
+ @Function        SysDevPAddrToSysPAddr
+
+ @Description     Compute a device physical address from a system physical
+	            address.
+
+ @Input           DevPAddr - device physical address.
+ @Input           eDeviceType - device type required if DevPAddr 
+		  address spaces vary across devices 
+		  in the same system
+
+ @Return        System physical address.
+
+******************************************************************************/
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR DevPAddr)
+{
+	IMG_SYS_PHYADDR SysPAddr;
+
+	PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+	/* Note: for UMA system we assume DevP == SysP */
+	SysPAddr.uiAddr = DevPAddr.uiAddr;
+
+	return SysPAddr;
+}
+
+
+/*****************************************************************************
+ @Function        SysRegisterExternalDevice
+
+ @Description     Called when a 3rd party device registers with services
+
+ @Input           psDeviceNode - the new device node.
+
+ @Return        IMG_VOID
+*****************************************************************************/
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+
+/*****************************************************************************
+ @Function        SysRemoveExternalDevice
+
+ @Description     Called when a 3rd party device unregisters from services
+
+ @Input           psDeviceNode - the device node being removed.
+
+ @Return        IMG_VOID
+*****************************************************************************/
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+	PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+/*!
+******************************************************************************
+ @Function        SysGetInterruptSource
+
+ @Description     Returns System specific information about the device(s) that
+				generated the interrupt in the system
+
+ @Input           psSysData
+ @Input           psDeviceNode
+
+ @Return        System specific information indicating which device(s) 
+				generated the interrupt
+
+******************************************************************************/
+IMG_UINT32 SysGetInterruptSource(SYS_DATA			*psSysData,
+								 PVRSRV_DEVICE_NODE	*psDeviceNode)
+{
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+#if defined(NO_HARDWARE)
+	/* no interrupts in no_hw system just return all bits */
+	return 0xFFFFFFFF;
+#else
+	/* Not a shared irq, so we know this is an interrupt for this device */
+	return psDeviceNode->ui32SOCInterruptBit;
+#endif
+}
+
+
+/*!
+******************************************************************************
+ @Function        SysClearInterrupts
+
+ @Description     Clears specified system interrupts
+
+ @Input           psSysData
+ @Input           ui32ClearBits
+
+ @Return        IMG_VOID
+
+******************************************************************************/
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
+{
+	PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+#if !defined(NO_HARDWARE)
+#if defined(SGX_OCP_NO_INT_BYPASS)
+	OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQSTATUS_2, 0x1);
+#endif
+	/* Flush posted writes */
+	OSReadHWReg(((PVRSRV_SGXDEV_INFO *)gpsSGXDevNode->pvDevice)->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR);
+#endif	/* defined(NO_HARDWARE) */
+}
+
+#if defined(SGX_OCP_NO_INT_BYPASS)
+/*!
+******************************************************************************
+ @Function        SysEnableSGXInterrupts
+
+ @Description     Enables SGX interrupts
+
+ @Input           psSysData
+
+ @Return        IMG_VOID
+
+******************************************************************************/
+IMG_VOID SysEnableSGXInterrupts(SYS_DATA *psSysData)
+{
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LISR) && !SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+	{
+		OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQSTATUS_2, 0x1);
+		OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQENABLE_SET_2, 0x1);
+		SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+	}
+}
+
+/*!
+******************************************************************************
+ @Function        SysDisableSGXInterrupts
+
+ @Description     Disables SGX interrupts
+
+ @Input           psSysData
+
+ @Return        IMG_VOID
+
+******************************************************************************/
+IMG_VOID SysDisableSGXInterrupts(SYS_DATA *psSysData)
+{
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+
+	if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+	{
+		OSWriteHWReg(gpvOCPRegsLinAddr, EUR_CR_OCP_IRQENABLE_CLR_2, 0x1);
+		SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+	}
+}
+#endif	/* defined(SGX_OCP_NO_INT_BYPASS) */
+
+/*!
+******************************************************************************
+
+ @Function	SysSystemPrePowerState
+
+ @Description	Perform system-level processing required before a power transition
+
+ @Input		eNewPowerState :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (eNewPowerState == PVRSRV_SYS_POWER_STATE_D3)
+	{
+		PVR_TRACE(("SysSystemPrePowerState: Entering state D3"));
+
+#if defined(SYS_USING_INTERRUPTS)
+		if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR))
+		{
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+			IMG_BOOL bWrapped = WrapSystemPowerChange(&gsSysSpecificData);
+#endif
+			eError = OSUninstallDeviceLISR(gpsSysData);
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+			if (bWrapped)
+			{
+				UnwrapSystemPowerChange(&gsSysSpecificData);
+			}
+#endif
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSUninstallDeviceLISR failed (%d)", eError));
+				return eError;
+			}
+			SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+			SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR);
+		}
+#endif
+
+		if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS))
+		{
+			DisableSystemClocks(gpsSysData);
+
+			SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS);
+			SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+		}
+	}
+
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysSystemPostPowerState
+
+ @Description	Perform system-level processing required after a power transition
+
+ @Input		eNewPowerState :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	if (eNewPowerState == PVRSRV_SYS_POWER_STATE_D0)
+	{
+		PVR_TRACE(("SysSystemPostPowerState: Entering state D0"));
+
+		if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS))
+		{
+			eError = EnableSystemClocksWrap(gpsSysData);
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: EnableSystemClocksWrap failed (%d)", eError));
+				return eError;
+			}
+			SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+			SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS);
+		}
+
+#if defined(SYS_USING_INTERRUPTS)
+		if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR))
+		{
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+			IMG_BOOL bWrapped = WrapSystemPowerChange(&gsSysSpecificData);
+#endif
+
+			eError = OSInstallDeviceLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ, "SGX ISR", gpsSGXDevNode);
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+			if (bWrapped)
+			{
+				UnwrapSystemPowerChange(&gsSysSpecificData);
+			}
+#endif
+			if (eError != PVRSRV_OK)
+			{
+				PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: OSInstallDeviceLISR failed to install ISR (%d)", eError));
+				return eError;
+			}
+			SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR);
+			SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+		}
+#endif
+	}
+	return eError;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysDevicePrePowerState
+
+ @Description	Perform system level processing required before a device power
+ 				transition
+
+ @Input		ui32DeviceIndex :
+ @Input		eNewPowerState :
+ @Input		eCurrentPowerState :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32				ui32DeviceIndex,
+									PVRSRV_DEV_POWER_STATE	eNewPowerState,
+									PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
+
+	if (ui32DeviceIndex != gui32SGXDeviceID)
+	{
+		return PVRSRV_OK;
+	}
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SysDevicePrePowerState: SGX Entering state D3"));
+		DisableSGXClocks(gpsSysData);
+	}
+#else	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+	PVR_UNREFERENCED_PARAMETER(eNewPowerState );
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function	SysDevicePostPowerState
+
+ @Description	Perform system level processing required after a device power
+ 				transition
+
+ @Input		ui32DeviceIndex :
+ @Input		eNewPowerState :
+ @Input		eCurrentPowerState :
+
+ @Return	PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32				ui32DeviceIndex,
+									 PVRSRV_DEV_POWER_STATE	eNewPowerState,
+									 PVRSRV_DEV_POWER_STATE	eCurrentPowerState)
+{
+	PVRSRV_ERROR eError = PVRSRV_OK;
+
+	PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+
+	if (ui32DeviceIndex != gui32SGXDeviceID)
+	{
+		return eError;
+	}
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+	{
+		PVR_DPF((PVR_DBG_MESSAGE, "SysDevicePostPowerState: SGX Leaving state D3"));
+		eError = EnableSGXClocksWrap(gpsSysData);
+	}
+#else	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+	PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
+#endif	/* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+
+	return eError;
+}
+
+/*****************************************************************************
+ @Function        SysOEMFunction
+
+ @Description     marshalling function for custom OEM functions
+
+ @Input           ui32ID  - function ID
+ @Input           pvIn - in data
+ @Output          pvOut - out data
+
+ @Return        PVRSRV_ERROR
+*****************************************************************************/
+PVRSRV_ERROR SysOEMFunction (	IMG_UINT32	ui32ID,
+								IMG_VOID	*pvIn,
+								IMG_UINT32	ulInSize,
+								IMG_VOID	*pvOut,
+								IMG_UINT32	ulOutSize)
+{
+	PVR_UNREFERENCED_PARAMETER(ui32ID);
+	PVR_UNREFERENCED_PARAMETER(pvIn);
+	PVR_UNREFERENCED_PARAMETER(ulInSize);
+	PVR_UNREFERENCED_PARAMETER(pvOut);
+	PVR_UNREFERENCED_PARAMETER(ulOutSize);
+
+#if !defined(__QNXNTO__)
+	if ((ui32ID == OEM_GET_EXT_FUNCS) &&
+		(ulOutSize == sizeof(PVRSRV_DC_OEM_JTABLE)))
+	{
+		PVRSRV_DC_OEM_JTABLE *psOEMJTable = (PVRSRV_DC_OEM_JTABLE*) pvOut;
+		psOEMJTable->pfnOEMBridgeDispatch = &PVRSRV_BridgeDispatchKM;
+		return PVRSRV_OK;
+	}
+#endif
+
+	return PVRSRV_ERROR_INVALID_PARAMS;
+}
+/******************************************************************************
+ End of file (sysconfig.c)
+******************************************************************************/
diff --git a/drivers/gpu/pvr/services4/system/omap/sysconfig.h b/drivers/gpu/pvr/services4/system/omap/sysconfig.h
new file mode 100644
index 0000000..54be563
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sysconfig.h
@@ -0,0 +1,113 @@
+/*************************************************************************/ /*!
+@Title          System Description Header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    This header provides system-specific declarations and macros
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__SOCCONFIG_H__)
+#define __SOCCONFIG_H__
+
+#if defined(VS_PRODUCT_VERSION) && VS_PRODUCT_VERSION == 5
+	#define VS_PRODUCT_NAME	"OMAP5"
+	#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ		(100)	// 10ms (100hz)
+#else
+	#define VS_PRODUCT_NAME	"OMAP4"
+	#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ		(50)	// 20ms (50hz)
+#endif
+
+#define SYS_SGX_PDS_TIMER_FREQ				(1000)	// 1ms (1000hz)
+
+/* Allow the AP latency to be overridden in the build config */
+#if !defined(SYS_SGX_ACTIVE_POWER_LATENCY_MS)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS		(2)
+#endif
+
+
+#define SYS_OMAP_SGX_REGS_SYS_PHYS_BASE  0x56000000
+#define SYS_OMAP_SGX_REGS_SIZE           0xFFFF
+
+#define SYS_OMAP_SGX_IRQ				 53 /* OMAP4 IRQ's are offset by 32 */
+
+#define SYS_OMAP_DSS_REGS_SYS_PHYS_BASE  0x58000000
+#define SYS_OMAP_DSS_REGS_SIZE           0x7000
+
+#define SYS_OMAP_DSS_HDMI_INTERRUPT_STATUS_REG 0x6028
+#define SYS_OMAP_DSS_HDMI_INTERRUPT_ENABLE_REG 0x602c
+
+#define SYS_OMAP_DSS_HDMI_INTERRUPT_VSYNC_ENABLE_MASK 0x10000
+#define SYS_OMAP_DSS_HDMI_INTERRUPT_VSYNC_STATUS_MASK 0x10000
+
+#define SYS_OMAP_DSS_LCD_INTERRUPT_STATUS_REG 0x1018
+#define SYS_OMAP_DSS_LCD_INTERRUPT_ENABLE_REG 0x101c
+
+#define SYS_OMAP_DSS_LCD_INTERRUPT_VSYNC_ENABLE_MASK 0x40002
+#define SYS_OMAP_DSS_LCD_INTERRUPT_VSYNC_STATUS_MASK 0x40002
+
+
+#define SYS_OMAP_GP11TIMER_ENABLE_SYS_PHYS_BASE	0x48088038
+#define SYS_OMAP_GP11TIMER_REGS_SYS_PHYS_BASE	0x4808803C
+#define SYS_OMAP_GP11TIMER_TSICR_SYS_PHYS_BASE	0x48088054
+
+/* Interrupt bits */
+#define DEVICE_SGX_INTERRUPT		(1<<0)
+#define DEVICE_MSVDX_INTERRUPT		(1<<1)
+#define DEVICE_DISP_INTERRUPT		(1<<2)
+
+#if defined(__linux__)
+#if defined(PVR_LDM_DEVICE_TREE)
+#define	SYS_SGX_DEV_NAME	"ti,dra7-sgx544"
+#else
+/*
+ * Recent OMAP4 kernels register SGX as platform device "omap_gpu".
+ * This device must be used with the Linux power management calls
+ * in sysutils_linux.c, in order for SGX to be powered on.
+ */
+#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED_DEV)
+#define	SYS_SGX_DEV_NAME	PVR_LDM_PLATFORM_PRE_REGISTERED_DEV
+#else
+#define	SYS_SGX_DEV_NAME	"omap_gpu"
+#endif	/* defined(PVR_LDM_PLATFORM_PRE_REGISTERED_DEV) */
+#endif	/* defined(PVR_LDM_DEVICE_TREE) */
+#endif	/* defined(__linux__) */
+
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
+ 
+#endif	/* __SYSCONFIG_H__ */
diff --git a/drivers/gpu/pvr/services4/system/omap/sysinfo.h b/drivers/gpu/pvr/services4/system/omap/sysinfo.h
new file mode 100644
index 0000000..8ba5943
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sysinfo.h
@@ -0,0 +1,70 @@
+/*************************************************************************/ /*!
+@Title          System Description Header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    This header provides system-specific declarations and macros
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#if defined(SGX540) && (SGX_CORE_REV == 120)
+#define SYS_SGX_CLOCK_SPEED		307200000
+#else
+#define SYS_SGX_CLOCK_SPEED		304742400
+#endif
+
+/*!< System specific poll/timeout details */
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+/*
+ * The workqueue based 3rd party display driver may be blocked for up
+ * to 500ms waiting for a vsync when the screen goes blank, so we
+ * need to wait longer for the hardware if a flush of the swap chain is
+ * required.
+ */
+#define MAX_HW_TIME_US				(1000000)
+#define WAIT_TRY_COUNT				(20000)
+#else
+#define MAX_HW_TIME_US				(2000000)
+#define WAIT_TRY_COUNT				(40000)
+#endif
+
+
+#define SYS_DEVICE_COUNT 15 /* SGX, DISPLAYCLASS (external), BUFFERCLASS (external) */
+
+#endif	/* __SYSINFO_H__ */
diff --git a/drivers/gpu/pvr/services4/system/omap/syslocal.h b/drivers/gpu/pvr/services4/system/omap/syslocal.h
new file mode 100644
index 0000000..bddbf6f
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/syslocal.h
@@ -0,0 +1,262 @@
+/*************************************************************************/ /*!
+@Title          Local system definitions
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    This header provides local system declarations and macros
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+#if !defined(__SYSLOCAL_H__)
+#define __SYSLOCAL_H__
+
+#if defined(__linux__)
+
+#include <linux/version.h>
+#include <linux/clk.h>
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/mutex.h>
+#else
+#include <linux/spinlock.h>
+#endif
+#include <asm/atomic.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+#include <linux/semaphore.h>
+#include <linux/resource.h>
+#else /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
+#include <asm/semaphore.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+#include <asm/arch/resource.h>
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) */
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+#if !defined(LDM_PLATFORM)
+#error "LDM_PLATFORM must be set"
+#endif
+#define	PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO
+#include <linux/platform_device.h>
+#endif
+
+#if ((defined(DEBUG) || defined(TIMING)) && \
+    (LINUX_VERSION_CODE == KERNEL_VERSION(2,6,34))) && \
+    !defined(PVR_NO_OMAP_TIMER)
+/*
+ * We need to explicitly enable the GPTIMER11 clocks, or we'll get an
+ * abort when we try to access the timer registers.
+ */
+#define	PVR_OMAP4_TIMING_PRCM
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,13))
+#include <plat/gpu.h>
+#endif
+#if !defined(PVR_NO_OMAP_TIMER)
+#define	PVR_OMAP_USE_DM_TIMER_API
+#include <plat/dmtimer.h>
+#endif
+#endif
+
+#if !defined(PVR_NO_OMAP_TIMER)
+#define PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA
+#endif
+#endif /* defined(__linux__) */
+
+#if !defined(NO_HARDWARE) && \
+     defined(SYS_USING_INTERRUPTS)
+#define SGX_OCP_REGS_ENABLED
+#endif
+
+#if defined(__linux__)
+#if defined(SGX_OCP_REGS_ENABLED)
+/* FIXME: Temporary workaround for OMAP4470 and active power off in 4430 */
+#if !defined(SGX544) && defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+#define SGX_OCP_NO_INT_BYPASS
+#endif
+#endif
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/*****************************************************************************
+ * system specific data structures
+ *****************************************************************************/
+ 
+/*****************************************************************************
+ * system specific function prototypes
+ *****************************************************************************/
+ 
+IMG_VOID DisableSystemClocks(SYS_DATA *psSysData);
+PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData);
+
+IMG_VOID DisableSGXClocks(SYS_DATA *psSysData);
+PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData);
+
+/*
+ * Various flags to indicate what has been initialised, and what
+ * has been temporarily deinitialised for power management purposes.
+ */
+#define SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS	0x00000001
+#define SYS_SPECIFIC_DATA_ENABLE_LISR		0x00000002
+#define SYS_SPECIFIC_DATA_ENABLE_MISR		0x00000004
+#define SYS_SPECIFIC_DATA_ENABLE_ENVDATA	0x00000008
+#define SYS_SPECIFIC_DATA_ENABLE_LOCDEV		0x00000010
+#define SYS_SPECIFIC_DATA_ENABLE_REGDEV		0x00000020
+#define SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT	0x00000040
+#define SYS_SPECIFIC_DATA_ENABLE_INITDEV	0x00000080
+#define SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV	0x00000100
+
+#define	SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR	0x00000200
+#define	SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS	0x00000400
+#define SYS_SPECIFIC_DATA_ENABLE_OCPREGS	0x00000800
+#define SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME	0x00001000
+#define SYS_SPECIFIC_DATA_IRQ_ENABLED		0x00002000
+#define SYS_SPECIFIC_DATA_DVFS_INIT			0x00004000
+
+#define	SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData |= (flag)))
+
+#define	SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData &= ~(flag)))
+
+#define	SYS_SPECIFIC_DATA_TEST(psSysSpecData, flag) (((psSysSpecData)->ui32SysSpecificData & (flag)) != 0)
+ 
+typedef struct _SYS_SPECIFIC_DATA_TAG_
+{
+	IMG_UINT32	ui32SysSpecificData;
+	PVRSRV_DEVICE_NODE *psSGXDevNode;
+	IMG_BOOL	bSGXInitComplete;
+#if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA)
+	IMG_CPU_PHYADDR	sTimerRegPhysBase;
+#endif
+#if !defined(__linux__)
+	IMG_BOOL	bSGXClocksEnabled;
+#endif
+	IMG_UINT32	ui32SrcClockDiv;
+#if defined(__linux__)
+	IMG_BOOL	bSysClocksOneTimeInit;
+	atomic_t	sSGXClocksEnabled;
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+	struct mutex	sPowerLock;
+#else
+	IMG_BOOL	bConstraintNotificationsEnabled;
+	spinlock_t	sPowerLock;
+	atomic_t	sPowerLockCPU;
+	spinlock_t	sNotifyLock;
+	atomic_t	sNotifyLockCPU;
+	IMG_BOOL	bCallVDD2PostFunc;
+#endif
+#if defined(DEBUG) || defined(TIMING)
+	struct clk	*psGPT11_FCK;
+	struct clk	*psGPT11_ICK;
+#endif
+#if defined(PVR_OMAP_USE_DM_TIMER_API)
+	struct omap_dm_timer *psGPTimer;
+#endif
+#endif	/* defined(__linux__) */
+} SYS_SPECIFIC_DATA;
+
+extern SYS_SPECIFIC_DATA *gpsSysSpecificData;
+
+#if defined(SGX_OCP_REGS_ENABLED) && defined(SGX_OCP_NO_INT_BYPASS)
+IMG_VOID SysEnableSGXInterrupts(SYS_DATA* psSysData);
+IMG_VOID SysDisableSGXInterrupts(SYS_DATA* psSysData);
+#else
+#define	SysEnableSGXInterrupts(psSysData)
+#define SysDisableSGXInterrupts(psSysData)
+#endif
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+IMG_BOOL WrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData);
+IMG_VOID UnwrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData);
+#endif
+
+#if defined(__linux__)
+
+PVRSRV_ERROR SysPMRuntimeRegister(void);
+PVRSRV_ERROR SysPMRuntimeUnregister(void);
+
+PVRSRV_ERROR SysDvfsInitialize(SYS_SPECIFIC_DATA *psSysSpecificData);
+PVRSRV_ERROR SysDvfsDeinitialize(SYS_SPECIFIC_DATA *psSysSpecificData);
+
+#else /* defined(__linux__) */
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysPMRuntimeRegister)
+#endif
+static INLINE PVRSRV_ERROR SysPMRuntimeRegister(void)
+{
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysPMRuntimeUnregister)
+#endif
+static INLINE PVRSRV_ERROR SysPMRuntimeUnregister(void)
+{
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDvfsInitialize)
+#endif
+static INLINE PVRSRV_ERROR SysDvfsInitialize(SYS_SPECIFIC_DATA *psSysSpecificData)
+{
+	PVR_UNREFERENCED_PARAMETER(psSysSpecificData);
+	return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDvfsDeinitialize)
+#endif
+static INLINE PVRSRV_ERROR SysDvfsDeinitialize(SYS_SPECIFIC_DATA *psSysSpecificData)
+{
+	PVR_UNREFERENCED_PARAMETER(psSysSpecificData);
+	return PVRSRV_OK;
+}
+
+#endif /* defined(__linux__) */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif	/* __SYSLOCAL_H__ */
+
+
diff --git a/drivers/gpu/pvr/services4/system/omap/sysutils.c b/drivers/gpu/pvr/services4/system/omap/sysutils.c
new file mode 100644
index 0000000..b1ea0558d
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sysutils.c
@@ -0,0 +1,63 @@
+/*************************************************************************/ /*!
+@Title          Shared (User/kernel) and System dependent utilities
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provides system-specific functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+
+/* Pull in the correct system dependent sysutils source */
+
+#if defined(__linux__)
+#include "sysutils_linux.c"
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+#include "sgxfreq.c"
+#include "sgxfreq_onoff.c"
+#include "sgxfreq_activeidle.c"
+#include "sgxfreq_on3demand.c"
+#include "sgxfreq_userspace.c"
+#if (defined(CONFIG_THERMAL) || defined(CONFIG_THERMAL_FRAMEWORK))
+#include "sgxfreq_cool.c"
+#endif
+#endif
+#endif
+
+
+
+#if defined(__QNXNTO__) 
+#include "sysutils_nto.c"
+#endif
diff --git a/drivers/gpu/pvr/services4/system/omap/sysutils_linux.c b/drivers/gpu/pvr/services4/system/omap/sysutils_linux.c
new file mode 100644
index 0000000..ad02673
--- /dev/null
+++ b/drivers/gpu/pvr/services4/system/omap/sysutils_linux.c
@@ -0,0 +1,721 @@
+/*************************************************************************/ /*!
+@Title          System dependent utilities
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Provides system-specific functions
+@License        Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/ /**************************************************************************/
+#include <linux/version.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sysinfo.h"
+#include "sgxapi_km.h"
+#include "sysconfig.h"
+#include "sgxinfokm.h"
+#include "syslocal.h"
+
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+#include "sgxfreq.h"
+#endif
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include <linux/omap_gpu.h>
+
+#include "pvr_drm.h"
+#endif
+
+#define	ONE_MHZ	1000000
+#define	HZ_TO_MHZ(m) ((m) / ONE_MHZ)
+
+#if defined(SUPPORT_OMAP3430_SGXFCLK_96M)
+#define SGX_PARENT_CLOCK "cm_96m_fck"
+#else
+#define SGX_PARENT_CLOCK "core_ck"
+#endif
+
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+extern struct platform_device *gpsPVRLDMDev;
+#endif
+
+static PVRSRV_ERROR PowerLockWrap(SYS_SPECIFIC_DATA *psSysSpecData, IMG_BOOL bTryLock)
+{
+	if (!in_interrupt())
+	{
+		if (bTryLock)
+		{
+			int locked = mutex_trylock(&psSysSpecData->sPowerLock);
+			if (locked == 0)
+			{
+				return PVRSRV_ERROR_RETRY;
+			}
+		}
+		else
+		{
+			mutex_lock(&psSysSpecData->sPowerLock);
+		}
+	}
+
+	return PVRSRV_OK;
+}
+
+static IMG_VOID PowerLockUnwrap(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+	if (!in_interrupt())
+	{
+		mutex_unlock(&psSysSpecData->sPowerLock);
+	}
+}
+
+PVRSRV_ERROR SysPowerLockWrap(IMG_BOOL bTryLock)
+{
+	SYS_DATA	*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	return PowerLockWrap(psSysData->pvSysSpecificData, bTryLock);
+}
+
+IMG_VOID SysPowerLockUnwrap(IMG_VOID)
+{
+	SYS_DATA	*psSysData;
+
+	SysAcquireData(&psSysData);
+
+	PowerLockUnwrap(psSysData->pvSysSpecificData);
+}
+
+/*
+ * This function should be called to unwrap the Services power lock, prior
+ * to calling any function that might sleep.
+ * This function shouldn't be called prior to calling EnableSystemClocks
+ * or DisableSystemClocks, as those functions perform their own power lock
+ * unwrapping.
+ * If the function returns IMG_TRUE, UnwrapSystemPowerChange must be
+ * called to rewrap the power lock, prior to returning to Services.
+ */
+IMG_BOOL WrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+	return IMG_TRUE;
+}
+
+IMG_VOID UnwrapSystemPowerChange(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+}
+
+/*
+ * Return SGX timining information to caller.
+ */
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psTimingInfo)
+{
+#if !defined(NO_HARDWARE)
+	PVR_ASSERT(atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0);
+#endif
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	/*
+	 * The core SGX driver and ukernel code expects SGX frequency
+	 * changes to occur only just prior to SGX initialization. We
+	 * don't wish to constrain the DVFS implementation as such. So
+	 * we let these components believe that frequency setting is
+	 * always at maximum. This produces safe values for derived
+	 * parameters such as APM and HWR timeouts.
+	 */
+	psTimingInfo->ui32CoreClockSpeed = (IMG_UINT32)sgxfreq_get_freq_max();
+#else /* defined(SYS_OMAP_HAS_DVFS_FRAMEWORK) */
+	psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+#endif
+	psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+	psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+	psTimingInfo->bEnableActivePM = IMG_TRUE;
+#else
+	psTimingInfo->bEnableActivePM = IMG_FALSE;
+#endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */
+	psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+}
+
+/*!
+******************************************************************************
+
+ @Function  EnableSGXClocks
+
+ @Description Enable SGX clocks
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR EnableSGXClocks(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+	/* SGX clocks already enabled? */
+	if (atomic_read(&psSysSpecData->sSGXClocksEnabled) != 0)
+	{
+		return PVRSRV_OK;
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE, "EnableSGXClocks: Enabling SGX Clocks"));
+
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+	{
+		/*
+		 * pm_runtime_get_sync returns 1 after the module has
+		 * been reloaded.
+		 */
+		int res = pm_runtime_get_sync(&gpsPVRLDMDev->dev);
+		if (res < 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "EnableSGXClocks: pm_runtime_get_sync failed (%d)", -res));
+			return PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK;
+		}
+	}
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	sgxfreq_notif_sgx_clk_on();
+#endif /* defined(SYS_OMAP_HAS_DVFS_FRAMEWORK) */
+#endif /* defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI) */
+
+	SysEnableSGXInterrupts(psSysData);
+
+	/* Indicate that the SGX clocks are enabled */
+	atomic_set(&psSysSpecData->sSGXClocksEnabled, 1);
+
+#else	/* !defined(NO_HARDWARE) */
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+#endif	/* !defined(NO_HARDWARE) */
+	return PVRSRV_OK;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function  DisableSGXClocks
+
+ @Description Disable SGX clocks.
+
+ @Return   none
+
+******************************************************************************/
+IMG_VOID DisableSGXClocks(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+	/* SGX clocks already disabled? */
+	if (atomic_read(&psSysSpecData->sSGXClocksEnabled) == 0)
+	{
+		return;
+	}
+
+	PVR_DPF((PVR_DBG_MESSAGE, "DisableSGXClocks: Disabling SGX Clocks"));
+
+	SysDisableSGXInterrupts(psSysData);
+
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+	{
+		int res = pm_runtime_put_sync(&gpsPVRLDMDev->dev);
+		if (res < 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "DisableSGXClocks: pm_runtime_put_sync failed (%d)", -res));
+		}
+	}
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	sgxfreq_notif_sgx_clk_off();
+#endif /* defined(SYS_OMAP_HAS_DVFS_FRAMEWORK) */
+#endif /* defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI) */
+
+	/* Indicate that the SGX clocks are disabled */
+	atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
+
+#else	/* !defined(NO_HARDWARE) */
+	PVR_UNREFERENCED_PARAMETER(psSysData);
+#endif	/* !defined(NO_HARDWARE) */
+}
+
+#if (defined(DEBUG) || defined(TIMING)) && !defined(PVR_NO_OMAP_TIMER)
+#if defined(PVR_OMAP_USE_DM_TIMER_API)
+#define	GPTIMER_TO_USE 11
+/*!
+******************************************************************************
+
+ @Function  AcquireGPTimer
+
+ @Description Acquire a GP timer
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+	PVR_ASSERT(psSysSpecData->psGPTimer == NULL);
+
+	/*
+	 * This code has problems on module reload for OMAP5 running Linux
+	 * 3.4.10, due to omap2_dm_timer_set_src (called by
+	 * omap_dm_timer_request_specific), being unable to set the parent
+	 * clock to OMAP_TIMER_SRC_32_KHZ.
+	 * Not calling omap_dm_timer_set_source doesn't help.
+	 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) || !defined(MODULE)
+	/*
+	 * This code could try requesting registers 9, 10, and 11,
+	 * stopping at the first succesful request.  We'll stick with
+	 * 11 for now, as it avoids having to hard code yet more
+	 * physical addresses into the code.
+	 */
+	psSysSpecData->psGPTimer = omap_dm_timer_request_specific(GPTIMER_TO_USE);
+	if (psSysSpecData->psGPTimer == NULL)
+	{
+	
+		PVR_DPF((PVR_DBG_WARNING, "%s: omap_dm_timer_request_specific failed", __FUNCTION__));
+		return PVRSRV_ERROR_CLOCK_REQUEST_FAILED;
+	}
+
+	omap_dm_timer_set_source(psSysSpecData->psGPTimer, OMAP_TIMER_SRC_SYS_CLK);
+	omap_dm_timer_enable(psSysSpecData->psGPTimer);
+
+	/* Set autoreload, and start value of 0 */
+	omap_dm_timer_set_load_start(psSysSpecData->psGPTimer, 1, 0);
+
+	omap_dm_timer_start(psSysSpecData->psGPTimer);
+
+	/*
+	 * The DM timer API doesn't have a mechanism for obtaining the
+	 * physical address of the counter register.
+	 */
+	psSysSpecData->sTimerRegPhysBase.uiAddr = SYS_OMAP_GP11TIMER_REGS_SYS_PHYS_BASE;
+#else	/* (LINUX_VERSION_CODE <= KERNEL_VERSION(3,4,0)) || !defined(MODULE) */
+	(void)psSysSpecData;
+#endif	/* (LINUX_VERSION_CODE <= KERNEL_VERSION(3,4,0)) || !defined(MODULE) */
+
+	return PVRSRV_OK;
+}
+
+/*!
+******************************************************************************
+
+ @Function  ReleaseGPTimer
+
+ @Description Release a GP timer
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+	if (psSysSpecData->psGPTimer != NULL)
+	{
+		/* Always returns 0 */	
+		(void) omap_dm_timer_stop(psSysSpecData->psGPTimer);
+
+		omap_dm_timer_disable(psSysSpecData->psGPTimer);
+
+		omap_dm_timer_free(psSysSpecData->psGPTimer);
+
+		psSysSpecData->sTimerRegPhysBase.uiAddr = 0;
+
+		psSysSpecData->psGPTimer = NULL;
+	}
+
+}
+#else	/* PVR_OMAP_USE_DM_TIMER_API */
+/*!
+******************************************************************************
+
+ @Function  AcquireGPTimer
+
+ @Description Acquire a GP timer
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+#if defined(PVR_OMAP4_TIMING_PRCM)
+	struct clk *psCLK;
+	IMG_INT res;
+	struct clk *sys_ck;
+	IMG_INT rate;
+#endif
+	PVRSRV_ERROR eError;
+
+	IMG_CPU_PHYADDR sTimerRegPhysBase;
+	IMG_HANDLE hTimerEnable;
+	IMG_UINT32 *pui32TimerEnable;
+
+	PVR_ASSERT(psSysSpecData->sTimerRegPhysBase.uiAddr == 0);
+
+#if defined(PVR_OMAP4_TIMING_PRCM)
+	/* assert our dependence on the GPTIMER11 module */
+	psCLK = clk_get(NULL, "gpt11_fck");
+	if (IS_ERR(psCLK))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 functional clock"));
+		goto ExitError;
+	}
+	psSysSpecData->psGPT11_FCK = psCLK;
+
+	psCLK = clk_get(NULL, "gpt11_ick");
+	if (IS_ERR(psCLK))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get GPTIMER11 interface clock"));
+		goto ExitError;
+	}
+	psSysSpecData->psGPT11_ICK = psCLK;
+
+	sys_ck = clk_get(NULL, "sys_clkin_ck");
+	if (IS_ERR(sys_ck))
+	{
+		PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't get System clock"));
+		goto ExitError;
+	}
+
+	if(clk_get_parent(psSysSpecData->psGPT11_FCK) != sys_ck)
+	{
+		PVR_TRACE(("Setting GPTIMER11 parent to System Clock"));
+		res = clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck);
+		if (res < 0)
+		{
+			PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't set GPTIMER11 parent clock (%d)", res));
+		goto ExitError;
+		}
+	}
+
+	rate = clk_get_rate(psSysSpecData->psGPT11_FCK);
+	PVR_TRACE(("GPTIMER11 clock is %dMHz", HZ_TO_MHZ(rate)));
+
+	res = clk_enable(psSysSpecData->psGPT11_FCK);
+	if (res < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't enable GPTIMER11 functional clock (%d)", res));
+		goto ExitError;
+	}
+
+	res = clk_enable(psSysSpecData->psGPT11_ICK);
+	if (res < 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: Couldn't enable GPTIMER11 interface clock (%d)", res));
+		goto ExitDisableGPT11FCK;
+	}
+#endif	/* defined(PVR_OMAP4_TIMING_PRCM) */
+
+	/* Set the timer to non-posted mode */
+	sTimerRegPhysBase.uiAddr = SYS_OMAP_GP11TIMER_TSICR_SYS_PHYS_BASE;
+	pui32TimerEnable = OSMapPhysToLin(sTimerRegPhysBase,
+                  4,
+                  PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                  &hTimerEnable);
+
+	if (pui32TimerEnable == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: OSMapPhysToLin failed"));
+		goto ExitDisableGPT11ICK;
+	}
+
+	if(!(*pui32TimerEnable & 4))
+	{
+		PVR_TRACE(("Setting GPTIMER11 mode to posted (currently is non-posted)"));
+
+		/* Set posted mode */
+		*pui32TimerEnable |= 4;
+	}
+
+	OSUnMapPhysToLin(pui32TimerEnable,
+		    4,
+		    PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+		    hTimerEnable);
+
+	/* Enable the timer */
+	sTimerRegPhysBase.uiAddr = SYS_OMAP_GP11TIMER_ENABLE_SYS_PHYS_BASE;
+	pui32TimerEnable = OSMapPhysToLin(sTimerRegPhysBase,
+                  4,
+                  PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+                  &hTimerEnable);
+
+	if (pui32TimerEnable == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "EnableSystemClocks: OSMapPhysToLin failed"));
+		goto ExitDisableGPT11ICK;
+	}
+
+	/* Enable and set autoreload on overflow */
+	*pui32TimerEnable = 3;
+
+	OSUnMapPhysToLin(pui32TimerEnable,
+		    4,
+		    PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+		    hTimerEnable);
+
+	psSysSpecData->sTimerRegPhysBase = sTimerRegPhysBase;
+
+	eError = PVRSRV_OK;
+
+	goto Exit;
+
+ExitDisableGPT11ICK:
+#if defined(PVR_OMAP4_TIMING_PRCM)
+	clk_disable(psSysSpecData->psGPT11_ICK);
+ExitDisableGPT11FCK:
+	clk_disable(psSysSpecData->psGPT11_FCK);
+ExitError:
+#endif	/* defined(PVR_OMAP4_TIMING_PRCM) */
+	eError = PVRSRV_ERROR_CLOCK_REQUEST_FAILED;
+Exit:
+	return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function  ReleaseGPTimer
+
+ @Description Release a GP timer
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+	IMG_HANDLE hTimerDisable;
+	IMG_UINT32 *pui32TimerDisable;
+
+	if (psSysSpecData->sTimerRegPhysBase.uiAddr == 0)
+	{
+		return;
+	}
+
+	/* Disable the timer */
+	pui32TimerDisable = OSMapPhysToLin(psSysSpecData->sTimerRegPhysBase,
+				4,
+				PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+				&hTimerDisable);
+
+	if (pui32TimerDisable == IMG_NULL)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "DisableSystemClocks: OSMapPhysToLin failed"));
+	}
+	else
+	{
+		*pui32TimerDisable = 0;
+
+		OSUnMapPhysToLin(pui32TimerDisable,
+				4,
+				PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+				hTimerDisable);
+	}
+
+	psSysSpecData->sTimerRegPhysBase.uiAddr = 0;
+
+#if defined(PVR_OMAP4_TIMING_PRCM)
+	clk_disable(psSysSpecData->psGPT11_ICK);
+
+	clk_disable(psSysSpecData->psGPT11_FCK);
+#endif	/* defined(PVR_OMAP4_TIMING_PRCM) */
+}
+#endif	/* PVR_OMAP_USE_DM_TIMER_API */
+#else	/* (DEBUG || TIMING) && !PVR_NO_OMAP_TIMER */
+static PVRSRV_ERROR AcquireGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+	PVR_UNREFERENCED_PARAMETER(psSysSpecData);
+
+	return PVRSRV_OK;
+}
+static void ReleaseGPTimer(SYS_SPECIFIC_DATA *psSysSpecData)
+{
+	PVR_UNREFERENCED_PARAMETER(psSysSpecData);
+}
+#endif /* (DEBUG || TIMING) && !PVR_NO_OMAP_TIMER */
+
+/*!
+******************************************************************************
+
+ @Function  EnableSystemClocks
+
+ @Description Setup up the clocks for the graphics device to work.
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR EnableSystemClocks(SYS_DATA *psSysData)
+{
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+	PVR_TRACE(("EnableSystemClocks: Enabling System Clocks"));
+
+	if (!psSysSpecData->bSysClocksOneTimeInit)
+	{
+		mutex_init(&psSysSpecData->sPowerLock);
+
+		atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
+
+		psSysSpecData->bSysClocksOneTimeInit = IMG_TRUE;
+	}
+
+	return AcquireGPTimer(psSysSpecData);
+}
+
+/*!
+******************************************************************************
+
+ @Function  DisableSystemClocks
+
+ @Description Disable the graphics clocks.
+
+ @Return  none
+
+******************************************************************************/
+IMG_VOID DisableSystemClocks(SYS_DATA *psSysData)
+{
+	SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+	PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
+
+	/*
+	 * Always disable the SGX clocks when the system clocks are disabled.
+	 * This saves having to make an explicit call to DisableSGXClocks if
+	 * active power management is enabled.
+	 */
+	DisableSGXClocks(psSysData);
+
+	ReleaseGPTimer(psSysSpecData);
+}
+
+PVRSRV_ERROR SysPMRuntimeRegister(void)
+{
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+	pm_runtime_enable(&gpsPVRLDMDev->dev);
+#endif
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysPMRuntimeUnregister(void)
+{
+#if defined(LDM_PLATFORM) && !defined(PVR_DRI_DRM_NOT_PCI)
+	pm_runtime_disable(&gpsPVRLDMDev->dev);
+#endif
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysDvfsInitialize(SYS_SPECIFIC_DATA *psSysSpecificData)
+{
+	PVR_UNREFERENCED_PARAMETER(psSysSpecificData);
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	if (sgxfreq_init(&gpsPVRLDMDev->dev))
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif /* defined(SYS_OMAP_HAS_DVFS_FRAMEWORK) */
+
+	return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SysDvfsDeinitialize(SYS_SPECIFIC_DATA *psSysSpecificData)
+{
+	PVR_UNREFERENCED_PARAMETER(psSysSpecificData);
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	if (sgxfreq_deinit())
+		return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif /* defined(SYS_OMAP_HAS_DVFS_FRAMEWORK) */
+
+	return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_DRI_DRM_PLUGIN)
+static struct omap_gpu_plugin sOMAPGPUPlugin;
+
+#define	SYS_DRM_SET_PLUGIN_FIELD(d, s, f) (d)->f = (s)->f
+int
+SysDRMRegisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin)
+{
+	int iRes;
+
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, name);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, open);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, load);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, unload);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, release);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, mmap);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, ioctls);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, num_ioctls);
+	SYS_DRM_SET_PLUGIN_FIELD(&sOMAPGPUPlugin, psDRMPlugin, ioctl_start);
+
+	iRes = omap_gpu_register_plugin(&sOMAPGPUPlugin);
+	if (iRes != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: omap_gpu_register_plugin failed (%d)", __FUNCTION__, iRes));
+	}
+
+	return iRes;
+}
+
+void
+SysDRMUnregisterPlugin(PVRSRV_DRM_PLUGIN *psDRMPlugin)
+{
+	int iRes = omap_gpu_unregister_plugin(&sOMAPGPUPlugin);
+	if (iRes != 0)
+	{
+		PVR_DPF((PVR_DBG_ERROR, "%s: omap_gpu_unregister_plugin failed (%d)", __FUNCTION__, iRes));
+	}
+}
+#endif
+
+IMG_VOID SysSGXIdleEntered(IMG_VOID)
+{
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	sgxfreq_notif_sgx_idle();
+#endif
+}
+
+IMG_VOID SysSGXCommandPending(IMG_BOOL bSGXIdle)
+{
+#if defined(SYS_OMAP_HAS_DVFS_FRAMEWORK)
+	if (bSGXIdle)
+		sgxfreq_notif_sgx_active();
+#else
+	PVR_UNREFERENCED_PARAMETER(bSGXIdle);
+#endif
+}
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
index 624718b..27f579a 100644
--- a/drivers/net/ethernet/ti/netcp_ethss.c
+++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -3697,12 +3697,17 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
 
 	ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device,
 				gbe_dev->dma_chan_name, gbe_dev->tx_queue_id);
-	if (ret)
+
+	if (ret) {
+		of_node_put(interfaces);
 		goto exit_err;
+	}
 
 	ret = netcp_txpipe_open(&gbe_dev->tx_pipe);
-	if (ret)
+	if (ret) {
+		of_node_put(interfaces);
 		goto exit_err;
+	}
 
 	/* Create network interfaces */
 	INIT_LIST_HEAD(&gbe_dev->gbe_intf_head);
@@ -3797,7 +3802,6 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
 
 free_sec_ports:
 	free_secondary_ports(gbe_dev);
-exit_err:
 	return ret;
 }
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3c20af9..ebb4639 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -20,6 +20,8 @@
 
 source "drivers/gpu/drm/Kconfig"
 
+source "drivers/gpu/pvr/Kconfig"
+
 menu "Frame buffer Devices"
 source "drivers/video/fbdev/Kconfig"
 endmenu
diff --git a/kernel/configs/android-base-arm.config b/kernel/configs/android-base-arm.config
index a0dc950..91c2d09 100644
--- a/kernel/configs/android-base-arm.config
+++ b/kernel/configs/android-base-arm.config
@@ -1,3 +1,5 @@
 #  KEEP ALPHABETICALLY SORTED
-# CONFIG_OABI_COMPAT is not set
+CONFIG_AEABI=y
 CONFIG_CPU_SW_DOMAIN_PAN=y
+# CONFIG_DEVKMEM is not set
+# CONFIG_OABI_COMPAT is not set
diff --git a/ti_config_fragments/android.cfg b/ti_config_fragments/android.cfg
index f1ae57a..ac17430 100644
--- a/ti_config_fragments/android.cfg
+++ b/ti_config_fragments/android.cfg
@@ -33,6 +33,7 @@
 
 # Software Sync Interface
 CONFIG_SW_SYNC=y
+CONFIG_PVR_SGX544=m
 
 # Misc
 CONFIG_DEVTMPFS=n