Merge tag 'lsk-v3.10-15.05-android' into develop-3.10
authorHuang, Tao <huangtao@rock-chips.com>
Tue, 2 Jun 2015 03:25:34 +0000 (11:25 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 2 Jun 2015 03:25:34 +0000 (11:25 +0800)
434 files changed:
Documentation/ABI/testing/sysfs-block-zram
Documentation/blockdev/zram.txt [new file with mode: 0644]
Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt
Makefile
android/configs/android-base.cfg
arch/alpha/mm/fault.c
arch/arc/kernel/signal.c
arch/arc/mm/fault.c
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/imx23-olinuxino.dts
arch/arm/boot/dts/imx25.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/include/asm/elf.h
arch/arm/mach-s3c64xx/crag6410.h
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm64/Kconfig
arch/arm64/kernel/Makefile
arch/arm64/kernel/entry.S
arch/arm64/kernel/psci-call.S [new file with mode: 0644]
arch/arm64/kernel/psci.c
arch/avr32/mm/fault.c
arch/c6x/kernel/time.c
arch/cris/mm/fault.c
arch/frv/mm/fault.c
arch/ia64/mm/fault.c
arch/m32r/mm/fault.c
arch/m68k/mm/fault.c
arch/metag/mm/fault.c
arch/microblaze/mm/fault.c
arch/mips/include/asm/suspend.h [deleted file]
arch/mips/mm/fault.c
arch/mips/power/cpu.c
arch/mips/power/hibernate.S
arch/mn10300/mm/fault.c
arch/openrisc/mm/fault.c
arch/parisc/mm/fault.c
arch/powerpc/kernel/suspend.c
arch/powerpc/mm/fault.c
arch/powerpc/perf/callchain.c
arch/powerpc/platforms/cell/spu_fault.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/s390/kernel/suspend.c
arch/s390/kvm/priv.c
arch/s390/mm/fault.c
arch/score/mm/fault.c
arch/sh/include/asm/sections.h
arch/sh/mm/fault.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/fault_64.c
arch/sparc/power/hibernate.c
arch/tile/mm/fault.c
arch/um/kernel/trap.c
arch/unicore32/include/mach/pm.h
arch/unicore32/kernel/hibernate.c
arch/x86/kvm/emulate.c
arch/x86/mm/fault.c
arch/x86/power/hibernate_32.c
arch/x86/power/hibernate_64.c
arch/xtensa/Kconfig
arch/xtensa/include/uapi/asm/unistd.h
arch/xtensa/mm/fault.c
arch/xtensa/platforms/xtfpga/Makefile
arch/xtensa/platforms/xtfpga/include/platform/hardware.h
arch/xtensa/platforms/xtfpga/include/platform/lcd.h
arch/xtensa/platforms/xtfpga/lcd.c
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/processor_idle.c
drivers/block/Kconfig
drivers/block/Makefile
drivers/block/nbd.c
drivers/block/rbd.c
drivers/block/zram/Kconfig [new file with mode: 0644]
drivers/block/zram/Makefile [new file with mode: 0644]
drivers/block/zram/zcomp.c [new file with mode: 0644]
drivers/block/zram/zcomp.h [new file with mode: 0644]
drivers/block/zram/zcomp_lz4.c [new file with mode: 0644]
drivers/block/zram/zcomp_lz4.h [new file with mode: 0644]
drivers/block/zram/zcomp_lzo.c [new file with mode: 0644]
drivers/block/zram/zcomp_lzo.h [new file with mode: 0644]
drivers/block/zram/zram_drv.c [new file with mode: 0644]
drivers/block/zram/zram_drv.h [new file with mode: 0644]
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/cpufreq/cpufreq_interactive.c
drivers/dma/omap-dma.c
drivers/edac/sb_edac.c
drivers/gator/COPYING [new file with mode: 0644]
drivers/gator/LICENSE [deleted file]
drivers/gator/Makefile
drivers/gator/gator.h
drivers/gator/gator_annotate.c
drivers/gator/gator_annotate_kernel.c
drivers/gator/gator_backtrace.c
drivers/gator/gator_buffer.c
drivers/gator/gator_buffer_write.c
drivers/gator/gator_cookies.c
drivers/gator/gator_events_armv6.c
drivers/gator/gator_events_armv7.c
drivers/gator/gator_events_block.c
drivers/gator/gator_events_irq.c
drivers/gator/gator_events_l2c-310.c
drivers/gator/gator_events_mali_4xx.c
drivers/gator/gator_events_mali_4xx.h
drivers/gator/gator_events_mali_common.c
drivers/gator/gator_events_mali_common.h
drivers/gator/gator_events_mali_midgard.c
drivers/gator/gator_events_mali_midgard_hw.c
drivers/gator/gator_events_mali_midgard_hw_test.c
drivers/gator/gator_events_meminfo.c
drivers/gator/gator_events_mmapped.c
drivers/gator/gator_events_net.c
drivers/gator/gator_events_perf_pmu.c
drivers/gator/gator_events_sched.c
drivers/gator/gator_events_scorpion.c
drivers/gator/gator_hrtimer_gator.c
drivers/gator/gator_iks.c
drivers/gator/gator_main.c
drivers/gator/gator_marshaling.c
drivers/gator/gator_trace_gpu.c
drivers/gator/gator_trace_power.c
drivers/gator/gator_trace_sched.c
drivers/gator/mali/mali_kbase_gator_api.h [deleted file]
drivers/gator/mali/mali_mjollnir_profiling_gator_api.h
drivers/gator/mali/mali_utgard_profiling_gator_api.h
drivers/gator/mali_midgard.mk
drivers/gpio/gpiolib.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/hv/channel.c
drivers/hv/channel_mgmt.c
drivers/i2c/i2c-core.c
drivers/iio/imu/adis_trigger.c
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/qp.c
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.h
drivers/media/platform/s5p-mfc/s5p_mfc_common.h
drivers/media/usb/stk1160/stk1160-v4l.c
drivers/memstick/core/mspro_block.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/card/queue.h
drivers/mtd/ubi/attach.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/wl.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/wireless/iwlwifi/dvm/dev.h
drivers/net/wireless/iwlwifi/dvm/ucode.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/ti/wl18xx/debugfs.c
drivers/net/wireless/ti/wlcore/debugfs.h
drivers/parport/Kconfig
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/devicetree.c
drivers/power/lp8788-charger.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/3w-sas.c
drivers/scsi/3w-sas.h
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/scsi_lib.c
drivers/scsi/storvsc_drv.c
drivers/spi/spidev.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/fiq_debugger/fiq_debugger.c
drivers/staging/panel/panel.c
drivers/staging/zram/Kconfig [deleted file]
drivers/staging/zram/Makefile [deleted file]
drivers/staging/zram/zram.txt [deleted file]
drivers/staging/zram/zram_drv.c [deleted file]
drivers/staging/zram/zram_drv.h [deleted file]
drivers/staging/zram/zram_sysfs.c [deleted file]
drivers/staging/zsmalloc/Makefile [deleted file]
drivers/staging/zsmalloc/zsmalloc-main.c [deleted file]
drivers/staging/zsmalloc/zsmalloc.h [deleted file]
drivers/target/iscsi/iscsi_target.c
drivers/tty/hvc/hvc_xen.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/of_serial.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hub.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/composite.c
drivers/usb/gadget/printer.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/oxu210hp-hcd.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/phy/phy.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/video/console/Kconfig
fs/affs/amigaffs.c
fs/autofs4/expire.c
fs/autofs4/root.c
fs/binfmt_elf.c
fs/btrfs/extent-tree.c
fs/btrfs/ioctl.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/cifs/file.c
fs/cifs/inode.c
fs/coda/cache.c
fs/dcache.c
fs/debugfs/inode.c
fs/exportfs/expfs.c
fs/ext4/extents_status.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/jfs/jfs_dtree.c
fs/libfs.c
fs/namei.c
fs/ncpfs/dir.c
fs/ncpfs/ncplib_kernel.h
fs/nfs/getroot.c
fs/nilfs2/btree.c
fs/notify/fsnotify.c
fs/ocfs2/dcache.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/file.c
fs/proc/task_mmu.c
fs/reiserfs/reiserfs.h
fs/splice.c
include/acpi/acpixf.h
include/acpi/actypes.h
include/acpi/platform/acenv.h
include/asm-generic/pgtable.h
include/asm-generic/sections.h
include/linux/blk_types.h
include/linux/ceph/decode.h
include/linux/cpu.h
include/linux/dcache.h
include/linux/interrupt.h
include/linux/kernel.h
include/linux/mm.h
include/linux/nilfs2_fs.h
include/linux/usb.h
include/linux/zpool.h [new file with mode: 0644]
include/linux/zsmalloc.h [new file with mode: 0644]
include/sound/emu10k1.h
ipc/compat.c
kernel/cgroup.c
kernel/cpu.c
kernel/printk.c
kernel/ptrace.c
kernel/softirq.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events.c
lib/string.c
mm/Kconfig
mm/Makefile
mm/ksm.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/page-writeback.c
mm/zpool.c [new file with mode: 0644]
mm/zsmalloc.c [new file with mode: 0644]
net/ipv4/ip_forward.c
net/ipv4/ping.c
net/ipv4/tcp_illinois.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/ndisc.c
net/ipv6/tcp_ipv6.c
net/llc/sysctl_net_llc.c
net/netfilter/nf_conntrack_proto_generic.c
net/netfilter/xt_IDLETIMER.c
net/rds/sysctl.c
security/selinux/avc.c
security/selinux/selinuxfs.c
security/selinux/ss/avtab.c
sound/oss/sequencer.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_callback.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/memory.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_realtek.c
sound/synth/emux/emux_oss.c
sound/synth/emux/emux_seq.c
sound/usb/mixer_quirks.c
tools/gator/daemon/Android.mk
tools/gator/daemon/AnnotateListener.cpp
tools/gator/daemon/AnnotateListener.h
tools/gator/daemon/Application.mk
tools/gator/daemon/Buffer.cpp
tools/gator/daemon/Buffer.h
tools/gator/daemon/CCNDriver.cpp
tools/gator/daemon/CCNDriver.h
tools/gator/daemon/COPYING [new file with mode: 0644]
tools/gator/daemon/CPUFreqDriver.cpp [deleted file]
tools/gator/daemon/CPUFreqDriver.h [deleted file]
tools/gator/daemon/CapturedXML.cpp
tools/gator/daemon/CapturedXML.h
tools/gator/daemon/Child.cpp
tools/gator/daemon/Child.h
tools/gator/daemon/Command.cpp
tools/gator/daemon/Command.h
tools/gator/daemon/Config.h
tools/gator/daemon/ConfigurationXML.cpp
tools/gator/daemon/ConfigurationXML.h
tools/gator/daemon/Counter.h
tools/gator/daemon/DiskIODriver.cpp
tools/gator/daemon/DiskIODriver.h
tools/gator/daemon/Driver.cpp
tools/gator/daemon/Driver.h
tools/gator/daemon/DriverSource.cpp
tools/gator/daemon/DriverSource.h
tools/gator/daemon/DynBuf.cpp
tools/gator/daemon/DynBuf.h
tools/gator/daemon/EventsXML.cpp
tools/gator/daemon/EventsXML.h
tools/gator/daemon/ExternalSource.cpp
tools/gator/daemon/ExternalSource.h
tools/gator/daemon/FSDriver.cpp
tools/gator/daemon/FSDriver.h
tools/gator/daemon/Fifo.cpp
tools/gator/daemon/Fifo.h
tools/gator/daemon/FtraceDriver.cpp
tools/gator/daemon/FtraceDriver.h
tools/gator/daemon/FtraceSource.cpp
tools/gator/daemon/FtraceSource.h
tools/gator/daemon/HwmonDriver.cpp
tools/gator/daemon/HwmonDriver.h
tools/gator/daemon/KMod.cpp
tools/gator/daemon/KMod.h
tools/gator/daemon/LocalCapture.cpp
tools/gator/daemon/LocalCapture.h
tools/gator/daemon/Logging.cpp
tools/gator/daemon/Logging.h
tools/gator/daemon/MaliVideoDriver.cpp
tools/gator/daemon/MaliVideoDriver.h
tools/gator/daemon/MemInfoDriver.cpp
tools/gator/daemon/MemInfoDriver.h
tools/gator/daemon/Monitor.cpp
tools/gator/daemon/Monitor.h
tools/gator/daemon/NetDriver.cpp
tools/gator/daemon/NetDriver.h
tools/gator/daemon/OlySocket.cpp
tools/gator/daemon/OlySocket.h
tools/gator/daemon/OlyUtility.cpp
tools/gator/daemon/OlyUtility.h
tools/gator/daemon/PerfBuffer.cpp
tools/gator/daemon/PerfBuffer.h
tools/gator/daemon/PerfDriver.cpp
tools/gator/daemon/PerfDriver.h
tools/gator/daemon/PerfGroup.cpp
tools/gator/daemon/PerfGroup.h
tools/gator/daemon/PerfSource.cpp
tools/gator/daemon/PerfSource.h
tools/gator/daemon/Proc.cpp
tools/gator/daemon/Proc.h
tools/gator/daemon/Sender.cpp
tools/gator/daemon/Sender.h
tools/gator/daemon/SessionData.cpp
tools/gator/daemon/SessionData.h
tools/gator/daemon/SessionXML.cpp
tools/gator/daemon/SessionXML.h
tools/gator/daemon/Setup.cpp
tools/gator/daemon/Setup.h
tools/gator/daemon/Source.cpp
tools/gator/daemon/Source.h
tools/gator/daemon/StreamlineSetup.cpp
tools/gator/daemon/StreamlineSetup.h
tools/gator/daemon/UEvent.cpp
tools/gator/daemon/UEvent.h
tools/gator/daemon/UserSpaceSource.cpp
tools/gator/daemon/UserSpaceSource.h
tools/gator/daemon/c++.cpp
tools/gator/daemon/common.mk
tools/gator/daemon/defaults.xml
tools/gator/daemon/escape.c
tools/gator/daemon/events-ARM11.xml
tools/gator/daemon/events-CCI-400.xml
tools/gator/daemon/events-CCI-500.xml [new file with mode: 0644]
tools/gator/daemon/events-Cortex-A15.xml
tools/gator/daemon/events-Cortex-A17.xml
tools/gator/daemon/events-Cortex-A5.xml
tools/gator/daemon/events-Cortex-A53.xml
tools/gator/daemon/events-Cortex-A57.xml
tools/gator/daemon/events-Cortex-A7.xml
tools/gator/daemon/events-Cortex-A72.xml [new file with mode: 0644]
tools/gator/daemon/events-Cortex-A8.xml
tools/gator/daemon/events-Cortex-A9.xml
tools/gator/daemon/events-Filesystem.xml
tools/gator/daemon/events-L2C-310.xml
tools/gator/daemon/events-Linux.xml
tools/gator/daemon/events-Mali-4xx.xml
tools/gator/daemon/events-Mali-Midgard.xml
tools/gator/daemon/events-Mali-Midgard_hw.xml
tools/gator/daemon/events-Mali-T60x_hw.xml
tools/gator/daemon/events-Mali-T62x_hw.xml
tools/gator/daemon/events-Mali-T72x_hw.xml
tools/gator/daemon/events-Mali-T76x_hw.xml
tools/gator/daemon/events-Mali-T82x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-T83x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-T86x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Mali-T88x_hw.xml [new file with mode: 0644]
tools/gator/daemon/events-Other.xml [new file with mode: 0644]
tools/gator/daemon/events-ftrace.xml
tools/gator/daemon/main.cpp
tools/power/x86/turbostat/Makefile
virt/kvm/kvm_main.c

index ec93fe33baa6bc853528dc7179adf1eec852078c..0c7f4f91c6b527923b0728cb7f19bd4ef67a1eac 100644 (file)
@@ -42,15 +42,48 @@ Description:
                The invalid_io file is read-only and specifies the number of
                non-page-size-aligned I/O requests issued to this device.
 
+What:          /sys/block/zram<id>/failed_reads
+Date:          February 2014
+Contact:       Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+               The failed_reads file is read-only and specifies the number of
+               failed reads happened on this device.
+
+What:          /sys/block/zram<id>/failed_writes
+Date:          February 2014
+Contact:       Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+               The failed_writes file is read-only and specifies the number of
+               failed writes happened on this device.
+
+What:          /sys/block/zram<id>/max_comp_streams
+Date:          February 2014
+Contact:       Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+               The max_comp_streams file is read-write and specifies the
+               number of backend's zcomp_strm compression streams (number of
+               concurrent compress operations).
+
+What:          /sys/block/zram<id>/comp_algorithm
+Date:          February 2014
+Contact:       Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+               The comp_algorithm file is read-write and lets to show
+               available and selected compression algorithms, change
+               compression algorithm selection.
+
 What:          /sys/block/zram<id>/notify_free
 Date:          August 2010
 Contact:       Nitin Gupta <ngupta@vflare.org>
 Description:
-               The notify_free file is read-only and specifies the number of
-               swap slot free notifications received by this device. These
-               notifications are send to a swap block device when a swap slot
-               is freed. This statistic is applicable only when this disk is
-               being used as a swap disk.
+               The notify_free file is read-only. Depending on device usage
+               scenario it may account a) the number of pages freed because
+               of swap slot free notifications or b) the number of pages freed
+               because of REQ_DISCARD requests sent by bio. The former ones
+               are sent to a swap block device when a swap slot is freed, which
+               implies that this disk is being used as a swap disk. The latter
+               ones are sent by filesystem mounted with discard option,
+               whenever some data blocks are getting discarded.
 
 What:          /sys/block/zram<id>/discard
 Date:          August 2010
@@ -97,3 +130,22 @@ Description:
                efficiency can be calculated using compr_data_size and this
                statistic.
                Unit: bytes
+
+What:          /sys/block/zram<id>/mem_used_max
+Date:          August 2014
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               The mem_used_max file is read/write and specifies the amount
+               of maximum memory zram have consumed to store compressed data.
+               For resetting the value, you should write "0". Otherwise,
+               you could see -EINVAL.
+               Unit: bytes
+
+What:          /sys/block/zram<id>/mem_limit
+Date:          August 2014
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               The mem_limit file is read/write and specifies the maximum
+               amount of memory ZRAM can use to store the compressed data.  The
+               limit could be changed in run time and "0" means disable the
+               limit.  No limit is the initial state.  Unit: bytes
diff --git a/Documentation/blockdev/zram.txt b/Documentation/blockdev/zram.txt
new file mode 100644 (file)
index 0000000..5cd0bd9
--- /dev/null
@@ -0,0 +1,129 @@
+zram: Compressed RAM based block devices
+----------------------------------------
+
+* Introduction
+
+The zram module creates RAM based block devices named /dev/zram<id>
+(<id> = 0, 1, ...). Pages written to these disks are compressed and stored
+in memory itself. These disks allow very fast I/O and compression provides
+good amounts of memory savings. Some of the usecases include /tmp storage,
+use as swap disks, various caches under /var and maybe many more :)
+
+Statistics for individual zram devices are exported through sysfs nodes at
+/sys/block/zram<id>/
+
+* Usage
+
+Following shows a typical sequence of steps for using zram.
+
+1) Load Module:
+       modprobe zram num_devices=4
+       This creates 4 devices: /dev/zram{0,1,2,3}
+       (num_devices parameter is optional. Default: 1)
+
+2) Set max number of compression streams
+       Compression backend may use up to max_comp_streams compression streams,
+       thus allowing up to max_comp_streams concurrent compression operations.
+       By default, compression backend uses single compression stream.
+
+       Examples:
+       #show max compression streams number
+       cat /sys/block/zram0/max_comp_streams
+
+       #set max compression streams number to 3
+       echo 3 > /sys/block/zram0/max_comp_streams
+
+Note:
+In order to enable compression backend's multi stream support max_comp_streams
+must be initially set to desired concurrency level before ZRAM device
+initialisation. Once the device initialised as a single stream compression
+backend (max_comp_streams equals to 1), you will see error if you try to change
+the value of max_comp_streams because single stream compression backend
+implemented as a special case by lock overhead issue and does not support
+dynamic max_comp_streams. Only multi stream backend supports dynamic
+max_comp_streams adjustment.
+
+3) Select compression algorithm
+       Using comp_algorithm device attribute one can see available and
+       currently selected (shown in square brackets) compression algortithms,
+       change selected compression algorithm (once the device is initialised
+       there is no way to change compression algorithm).
+
+       Examples:
+       #show supported compression algorithms
+       cat /sys/block/zram0/comp_algorithm
+       lzo [lz4]
+
+       #select lzo compression algorithm
+       echo lzo > /sys/block/zram0/comp_algorithm
+
+4) Set Disksize
+        Set disk size by writing the value to sysfs node 'disksize'.
+        The value can be either in bytes or you can use mem suffixes.
+        Examples:
+            # Initialize /dev/zram0 with 50MB disksize
+            echo $((50*1024*1024)) > /sys/block/zram0/disksize
+
+            # Using mem suffixes
+            echo 256K > /sys/block/zram0/disksize
+            echo 512M > /sys/block/zram0/disksize
+            echo 1G > /sys/block/zram0/disksize
+
+Note:
+There is little point creating a zram of greater than twice the size of memory
+since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
+size of the disk when not in use so a huge zram is wasteful.
+
+5) Set memory limit: Optional
+       Set memory limit by writing the value to sysfs node 'mem_limit'.
+       The value can be either in bytes or you can use mem suffixes.
+       In addition, you could change the value in runtime.
+       Examples:
+           # limit /dev/zram0 with 50MB memory
+           echo $((50*1024*1024)) > /sys/block/zram0/mem_limit
+
+           # Using mem suffixes
+           echo 256K > /sys/block/zram0/mem_limit
+           echo 512M > /sys/block/zram0/mem_limit
+           echo 1G > /sys/block/zram0/mem_limit
+
+           # To disable memory limit
+           echo 0 > /sys/block/zram0/mem_limit
+
+6) Activate:
+       mkswap /dev/zram0
+       swapon /dev/zram0
+
+       mkfs.ext4 /dev/zram1
+       mount /dev/zram1 /tmp
+
+7) Stats:
+       Per-device statistics are exported as various nodes under
+       /sys/block/zram<id>/
+               disksize
+               num_reads
+               num_writes
+               invalid_io
+               notify_free
+               discard
+               zero_pages
+               orig_data_size
+               compr_data_size
+               mem_used_total
+               mem_used_max
+
+8) Deactivate:
+       swapoff /dev/zram0
+       umount /dev/zram1
+
+9) Reset:
+       Write any positive value to 'reset' sysfs node
+       echo 1 > /sys/block/zram0/reset
+       echo 1 > /sys/block/zram1/reset
+
+       This frees all the memory allocated for the given device and
+       resets the disksize to zero. You must set the disksize again
+       before reusing the device.
+
+Nitin Gupta
+ngupta@vflare.org
index a4873e5e3e36de172c49f59108360e32aca9fefd..e30e184f50c727aa84d2284914581ce9927dba1c 100644 (file)
@@ -38,7 +38,7 @@ dma_apbx: dma-apbx@80024000 {
                      80 81 68 69
                      70 71 72 73
                      74 75 76 77>;
-       interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+       interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
                          "saif0", "saif1", "i2c0", "i2c1",
                          "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
                          "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
index fa41a5c931738273e6830c44a360a734431d8b8f..27d6cca60c7b9294e3a9b119b6fbb33d9c8328b7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 10
-SUBLEVEL = 74
+SUBLEVEL = 79
 EXTRAVERSION =
 NAME = TOSSUG Baby Fish
 
index 3ddcecd716beef3369ecf80352a2be5cc67da5c1..1bee5d614d1bc74e13073181911b73e4845c4af4 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_ARMV7_COMPAT=y
 CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CGROUPS=y
@@ -51,6 +52,7 @@ CONFIG_IP_NF_MATCH_AH=y
 CONFIG_IP_NF_MATCH_ECN=y
 CONFIG_IP_NF_MATCH_TTL=y
 CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
 CONFIG_IP_NF_TARGET_NETMAP=y
 CONFIG_IP_NF_TARGET_REDIRECT=y
@@ -85,10 +87,12 @@ CONFIG_NETFILTER_XT_MATCH_TIME=y
 CONFIG_NETFILTER_XT_MATCH_U32=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_SECMARK=y
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
 CONFIG_NETFILTER_XT_TARGET_TPROXY=y
 CONFIG_NETFILTER_XT_TARGET_TRACE=y
@@ -110,6 +114,7 @@ CONFIG_NF_CONNTRACK_IRC=y
 CONFIG_NF_CONNTRACK_NETBIOS_NS=y
 CONFIG_NF_CONNTRACK_PPTP=y
 CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_TFTP=y
 CONFIG_NF_CT_NETLINK=y
 CONFIG_NF_CT_PROTO_DCCP=y
@@ -130,6 +135,11 @@ CONFIG_PREEMPT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SND=y
+CONFIG_SOUND=y
 CONFIG_STAGING=y
 CONFIG_SWITCH=y
 CONFIG_SYNC=y
index 98838a05ba6d89f0459742131010f57c38cbed05..9d0ac091a52a7d16cf1f78f402ab48c511924a24 100644 (file)
@@ -156,6 +156,8 @@ retry:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 7e95e1a86510fee2f2e1511f8bc7b63f8fb48122..6763654239a22979bbf21649f07e9bb2edfbdf5c 100644 (file)
@@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn)
        /* Don't restart from sigreturn */
        syscall_wont_restart(regs);
 
+       /*
+        * Ensure that sigreturn always returns to user mode (in case the
+        * regs saved on user stack got fudged between save and sigreturn)
+        * Otherwise it is easy to panic the kernel with a custom
+        * signal handler and/or restorer which clobberes the status32/ret
+        * to return to a bogus location in kernel mode.
+        */
+       regs->status32 |= STATUS_U_MASK;
+
        return regs->r0;
 
 badframe:
@@ -234,8 +243,11 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
 
        /*
         * handler returns using sigreturn stub provided already by userpsace
+        * If not, nuke the process right away
         */
-       BUG_ON(!(ka->sa.sa_flags & SA_RESTORER));
+       if(!(ka->sa.sa_flags & SA_RESTORER))
+               return 1;
+
        regs->blink = (unsigned long)ka->sa.sa_restorer;
 
        /* User Stack for signal handler will be above the frame just carved */
@@ -302,12 +314,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
              struct pt_regs *regs)
 {
        sigset_t *oldset = sigmask_to_save();
-       int ret;
+       int failed;
 
        /* Set up the stack frame */
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
+       failed = setup_rt_frame(sig, ka, info, oldset, regs);
 
-       if (ret)
+       if (failed)
                force_sigsegv(sig, current);
        else
                signal_delivered(sig, info, ka, regs, 0);
index 50533b750a99d88dfd7e0fa1d89deb87717f9095..08f65bcf9130fcefa7349af94da44acc76d1c084 100644 (file)
@@ -160,6 +160,8 @@ good_area:
        /* TBD: switch to pagefault_out_of_memory() */
        if (fault & VM_FAULT_OOM)
                goto out_of_memory;
+       else if (fault & VM_FAULT_SIGSEGV)
+               goto bad_area;
        else if (fault & VM_FAULT_SIGBUS)
                goto do_sigbus;
 
index 9746d0e7fcb4469a72115154696fee98eced5eed..5dfb3d354470b15e20090369d54f3e44b69a0ad2 100644 (file)
                          0xf0000000 0 0xf0000000 0x8000000     /* Device Bus, NOR 128MiB   */>;
 
                internal-regs {
+                       rtc@10300 {
+                               /* No crystal connected to the internal RTC */
+                               status = "disabled";
+                       };
                        serial@12000 {
                                clock-frequency = <250000000>;
                                status = "okay";
index 6cab46849cdb471d44b81ddf21f216999c6baeb4..d1e47092d21ac480169b97d4ef424d4ba309905c 100644 (file)
@@ -75,7 +75,7 @@
 
                uart2: serial@12200 {
                        compatible = "ns16550a";
-                       reg = <0x12000 0x100>;
+                       reg = <0x12200 0x100>;
                        reg-shift = <2>;
                        interrupts = <9>;
                        clocks = <&core_clk 0>;
@@ -84,7 +84,7 @@
 
                uart3: serial@12300 {
                        compatible = "ns16550a";
-                       reg = <0x12100 0x100>;
+                       reg = <0x12300 0x100>;
                        reg-shift = <2>;
                        interrupts = <10>;
                        clocks = <&core_clk 0>;
index cdbdc4dfef2284f18840ccc250b05b2c2f5155ef..19b9109891890b38e1440a81bd1fdb6c12bf1210 100644 (file)
                             <1 14 0xf08>,
                             <1 11 0xf08>,
                             <1 10 0xf08>;
+               /* Unfortunately we need this since some versions of U-Boot
+                * on Exynos don't set the CNTFRQ register, so we need the
+                * value from DT.
+                */
+               clock-frequency = <24000000>;
        };
 
        combiner:interrupt-controller@10440000 {
index d107c4af321ff374807ba7a1486d54816be708a0..6fef54416cbf1361517801e5dc29631670070b7a 100644 (file)
@@ -89,6 +89,7 @@
 
        ahb@80080000 {
                usb0: usb@80080000 {
+                       dr_mode = "host";
                        vbus-supply = <&reg_usb0_vbus>;
                        status = "okay";
                };
index 97d1a550eb98f831bc5a75582e049c5b83ee669e..2a571bcacaf442f45eb0ba6d0363b30f7738d4f6 100644 (file)
 
                        pwm4: pwm@53fc8000 {
                                compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+                               #pwm-cells = <2>;
                                reg = <0x53fc8000 0x4000>;
                                clocks = <&clks 108>, <&clks 52>;
                                clock-names = "ipg", "per";
index 4c10a1968c0e3a6d8d4331c7f26af13d0f6a4f97..2e76b84c6bad69ae4dfd3280ce16f2ee597744ea 100644 (file)
                                              80 81 68 69
                                              70 71 72 73
                                              74 75 76 77>;
-                               interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+                               interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
                                                  "saif0", "saif1", "i2c0", "i2c1",
                                                  "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
                                                  "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
index 26b6d5366ecaf1c6d5cf680c774054a332197bfb..2b2fdde412610fa34f0db78aa6b78e9e1e34ed9c 100644 (file)
@@ -115,7 +115,7 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE        (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE        (TASK_SIZE / 3 * 2)
 
 /* When the program starts, a1 contains a pointer to a function to be 
    registered with atexit, as per the SVR4 ABI.  A value of 0 means we 
index 4c3c9994fc2c2bac09fa6bb02de090664694b713..81dc722ced57bbfc7f1b4192f28c965d5515057f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/gpio.h>
 
 #define GLENFARCLAS_PMIC_IRQ_BASE      IRQ_BOARD_START
+#define BANFF_PMIC_IRQ_BASE            (IRQ_BOARD_START + 64)
 
 #define PCA935X_GPIO_BASE              GPIO_BOARD_START
 #define CODEC_GPIO_BASE                        (GPIO_BOARD_START + 8)
index 8ad88ace795a41cc617a1cdba91aa08e46856e04..5fa9ac9104e10f3c11207e56e94e55b67923594c 100644 (file)
@@ -558,6 +558,7 @@ static struct wm831x_touch_pdata touch_pdata = {
 
 static struct wm831x_pdata crag_pmic_pdata = {
        .wm831x_num = 1,
+       .irq_base = BANFF_PMIC_IRQ_BASE,
        .gpio_base = BANFF_PMIC_GPIO_BASE,
        .soft_shutdown = true,
 
index 72b758667ae462dbcc54dd14ea68c3badd74e372..135f9ca7874c28a411a7d3af232a19c3be8a46ff 100644 (file)
@@ -168,6 +168,32 @@ endmenu
 
 menu "Kernel Features"
 
+menu "ARM errata workarounds"
+
+config ARM64_ERRATUM_845719
+       bool "Cortex-A53: 845719: a load might read incorrect data"
+       depends on COMPAT
+       default n
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 845719 on Cortex-A53 parts up to r0p4.
+
+         When running a compat (AArch32) userspace on an affected Cortex-A53
+         part, a load at EL0 from a virtual address that matches the bottom 32
+         bits of the virtual address used by a recent load at (AArch64) EL1
+         might return incorrect data.
+
+         The workaround is to write the contextidr_el1 register on exception
+         return to a 32-bit task.
+         Please note that this does not necessarily enable the workaround,
+         as it depends on the alternative framework, which will only patch
+         the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
+endmenu
+
+
 config ARM64_64K_PAGES
        bool "Enable 64KB pages support"
        help
index 58895f0ba9385f50d7c3d0b44c0be08b90dfd552..b52313653742ba62416b0ef5aedcf2a71aeb430e 100644 (file)
@@ -15,7 +15,7 @@ CFLAGS_REMOVE_return_address.o = -pg
 arm64-obj-y            := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
                           entry-fpsimd.o process.o ptrace.o setup.o signal.o   \
                           sys.o stacktrace.o time.o traps.o io.o vdso.o        \
-                          hyp-stub.o psci.o cpu_ops.o insn.o return_address.o \
+                          hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o return_address.o \
                           opcodes.o
 
 arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o \
index e6681c26d4899a58637f6f9cc4e2ef020e0e4100..bd30119fd0c34db86e96604c1c7bf36b399cbfa8 100644 (file)
        ldp     x21, x22, [sp, #S_PC]           // load ELR, SPSR
        .if     \el == 0
        ldr     x23, [sp, #S_SP]                // load return stack pointer
+#ifdef CONFIG_ARM64_ERRATUM_845719
+       tbz     x22, #4, 1f
+#ifdef CONFIG_PID_IN_CONTEXTIDR
+       mrs     x29, contextidr_el1
+       msr     contextidr_el1, x29
+1:
+#else
+       msr     contextidr_el1, xzr
+1:
+#endif
+#endif
        .endif
        .if     \ret
        ldr     x1, [sp, #S_X1]                 // preserve x0 (syscall return)
diff --git a/arch/arm64/kernel/psci-call.S b/arch/arm64/kernel/psci-call.S
new file mode 100644 (file)
index 0000000..cf83e61
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2015 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/linkage.h>
+
+/* int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */
+ENTRY(__invoke_psci_fn_hvc)
+       hvc     #0
+       ret
+ENDPROC(__invoke_psci_fn_hvc)
+
+/* int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */
+ENTRY(__invoke_psci_fn_smc)
+       smc     #0
+       ret
+ENDPROC(__invoke_psci_fn_smc)
index d356b8d4531c9a00e378a258e2a5e12f34d57979..bfcf55da61b3b4acd67e69627dcb614fd4eeddf7 100644 (file)
@@ -59,6 +59,9 @@ static struct psci_operations psci_ops;
 static int (*invoke_psci_fn)(u64, u64, u64, u64);
 typedef int (*psci_initcall_t)(const struct device_node *);
 
+asmlinkage int __invoke_psci_fn_hvc(u64, u64, u64, u64);
+asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64);
+
 enum psci_function {
        PSCI_FN_CPU_SUSPEND,
        PSCI_FN_CPU_ON,
@@ -111,40 +114,6 @@ static void psci_power_state_unpack(u32 power_state,
                        PSCI_0_2_POWER_STATE_AFFL_SHIFT;
 }
 
-/*
- * The following two functions are invoked via the invoke_psci_fn pointer
- * and will not be inlined, allowing us to piggyback on the AAPCS.
- */
-static noinline int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1,
-                                        u64 arg2)
-{
-       asm volatile(
-                       __asmeq("%0", "x0")
-                       __asmeq("%1", "x1")
-                       __asmeq("%2", "x2")
-                       __asmeq("%3", "x3")
-                       "hvc    #0\n"
-               : "+r" (function_id)
-               : "r" (arg0), "r" (arg1), "r" (arg2));
-
-       return function_id;
-}
-
-static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
-                                        u64 arg2)
-{
-       asm volatile(
-                       __asmeq("%0", "x0")
-                       __asmeq("%1", "x1")
-                       __asmeq("%2", "x2")
-                       __asmeq("%3", "x3")
-                       "smc    #0\n"
-               : "+r" (function_id)
-               : "r" (arg0), "r" (arg1), "r" (arg2));
-
-       return function_id;
-}
-
 static int psci_get_version(void)
 {
        int err;
index 0eca93327195077ec16bdfd99efd7294c6ab2de6..d223a8b57c1eaad282289e75089654153ab598d6 100644 (file)
@@ -142,6 +142,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 356ee84cad95aef68e6e9aca6f88b42e0eb931ec..04845aaf59858f81feebeeca6c45096b48c313d8 100644 (file)
@@ -49,7 +49,7 @@ u64 sched_clock(void)
        return (tsc * sched_clock_multiplier) >> SCHED_CLOCK_SHIFT;
 }
 
-void time_init(void)
+void __init time_init(void)
 {
        u64 tmp = (u64)NSEC_PER_SEC << SCHED_CLOCK_SHIFT;
 
index 1790f22e71a21a859b2b7b1942cbbc503c2d557e..2686a7aa8ec82c50f29592840185b519522c53a7 100644 (file)
@@ -176,6 +176,8 @@ retry:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 9a66372fc7c76019ca874a9c3780c2fc8392266c..ec4917ddf67872aa46b60c6b067b0a67ec5417a4 100644 (file)
@@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 7225dad87094d81e89459e5a61909fa5b2d10ca0..ba5ba7accd0d6bb4dbab34f7fc307c4306347f4a 100644 (file)
@@ -172,6 +172,8 @@ retry:
                 */
                if (fault & VM_FAULT_OOM) {
                        goto out_of_memory;
+               } else if (fault & VM_FAULT_SIGSEGV) {
+                       goto bad_area;
                } else if (fault & VM_FAULT_SIGBUS) {
                        signal = SIGBUS;
                        goto bad_area;
index e9c6a8014bd647eec50a66afb5bc75b076b35e4d..e3d4d4890104cc27e2eb9de2f22cb6f53f939c90 100644 (file)
@@ -200,6 +200,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index eb1d61f6872549991dae7d5e491a74627d8456d0..f0eef0491f77bbb72ed376492abc2624d2042cf1 100644 (file)
@@ -153,6 +153,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto map_err;
                else if (fault & VM_FAULT_SIGBUS)
                        goto bus_err;
                BUG();
index 332680e5ebf23c7909b796c415c2273efd77ba3c..2de5dc695a87fa96d41a83e127166a7126d10df0 100644 (file)
@@ -141,6 +141,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index fa4cf52aa7a6d386711690005a314ece7d67fc53..d46a5ebb7570e07869ea03b9b995374aa3bff82e 100644 (file)
@@ -224,6 +224,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
diff --git a/arch/mips/include/asm/suspend.h b/arch/mips/include/asm/suspend.h
deleted file mode 100644 (file)
index 3adac3b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_SUSPEND_H
-#define __ASM_SUSPEND_H
-
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
-#endif /* __ASM_SUSPEND_H */
index 0214a43b9911b00e552d99c3396b07f9f12f6481..c40a8d1c43baaf5267c2f01e325c7108540b7f07 100644 (file)
@@ -157,6 +157,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 521e5963df05f4f67038f52dd3b321851fa0e551..2129e67723ff38b6a1ef8fea8401886a063c8402 100644 (file)
@@ -7,7 +7,7 @@
  * Author: Hu Hongbing <huhb@lemote.com>
  *        Wu Zhangjin <wuzhangjin@gmail.com>
  */
-#include <asm/suspend.h>
+#include <asm/sections.h>
 #include <asm/fpu.h>
 #include <asm/dsp.h>
 
index 32a7c828f073be90c228756e3e0712c8ea6c195e..e7567c8a9e79659ac1420375d77c12623a630188 100644 (file)
@@ -30,6 +30,8 @@ LEAF(swsusp_arch_suspend)
 END(swsusp_arch_suspend)
 
 LEAF(swsusp_arch_resume)
+       /* Avoid TLB mismatch during and after kernel resume */
+       jal local_flush_tlb_all
        PTR_L t0, restore_pblist
 0:
        PTR_L t1, PBE_ADDRESS(t0)   /* source */
@@ -43,7 +45,6 @@ LEAF(swsusp_arch_resume)
        bne t1, t3, 1b
        PTR_L t0, PBE_NEXT(t0)
        bnez t0, 0b
-       jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
        PTR_LA t0, saved_regs
        PTR_L ra, PT_R31(t0)
        PTR_L sp, PT_R29(t0)
index 3516cbdf1ee93acb82ebef6428f79df9af104514..0c2cc5d39c8e37ce1cfe5be191902bc435c41090 100644 (file)
@@ -262,6 +262,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 0703acf7d3276811919fd3d398ada99b1b9c6d50..230ac20ae7944f71636e5083fdaf3f034eb10af2 100644 (file)
@@ -171,6 +171,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index d10d27a720c0d1f323c2248f01cc93193e73ca1e..c45130f56a93ee18a16526be5ac19c0596567931 100644 (file)
@@ -220,6 +220,8 @@ good_area:
                 */
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto bad_area;
                BUG();
index 0167d53da30cbbbb1e61c8cdb8768db35e4b3e7a..a531154cc0f3a43f06edbba75e3207ab92b105d5 100644 (file)
@@ -9,9 +9,7 @@
 
 #include <linux/mm.h>
 #include <asm/page.h>
-
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
+#include <asm/sections.h>
 
 /*
  *     pfn_is_nosave - check if given pfn is in the 'nosave' section
index d9196c9f93d9dd7c1cb075fa3e0b732cd0ba9993..d51a0c110eb4a402c4db5165af1100f54a669b1b 100644 (file)
@@ -425,6 +425,8 @@ good_area:
         */
        fault = handle_mm_fault(mm, vma, address, flags);
        if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
+               if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                rc = mm_fault_error(regs, address, fault);
                if (rc >= MM_FAULT_RETURN)
                        goto bail;
index 2396dda282cdef0ed5c11c6ab7c3f4f479d0ac04..ead55351b2542accc663c496be8592b9c3942b08 100644 (file)
@@ -243,7 +243,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
        sp = regs->gpr[1];
        perf_callchain_store(entry, next_ip);
 
-       for (;;) {
+       while (entry->nr < PERF_MAX_STACK_DEPTH) {
                fp = (unsigned long __user *) sp;
                if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))
                        return;
index 641e7273d75ae687335716c5b4e87c9afcdb98c7..62f3e4e48a0b235a0bfe6ad577feccc8a3dc36aa 100644 (file)
@@ -75,7 +75,7 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
                if (*flt & VM_FAULT_OOM) {
                        ret = -ENOMEM;
                        goto out_unlock;
-               } else if (*flt & VM_FAULT_SIGBUS) {
+               } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
                        ret = -EFAULT;
                        goto out_unlock;
                }
index 35f77a42bedf7e5d1324b170faa51cd1689541d3..c5c5788e8a13e4842c47faf0ace955ef5bc58c36 100644 (file)
@@ -164,7 +164,7 @@ static void spufs_prune_dir(struct dentry *dir)
        struct dentry *dentry, *tmp;
 
        mutex_lock(&dir->d_inode->i_mutex);
-       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+       list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
                spin_lock(&dentry->d_lock);
                if (!(d_unhashed(dentry)) && dentry->d_inode) {
                        dget_dlock(dentry);
index c479d2f9605ba6ef3dede5a669be872f97494b0f..58cbb75e89e90b6e46ea7ce27844d6d08526aede 100644 (file)
@@ -9,12 +9,9 @@
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/mm.h>
+#include <asm/sections.h>
 #include <asm/ctl_reg.h>
-
-/*
- * References to section boundaries
- */
-extern const void __nosave_begin, __nosave_end;
+#include <asm/ipl.h>
 
 /*
  * The restore of the saved pages in an hibernation image will set
@@ -138,6 +135,8 @@ int pfn_is_nosave(unsigned long pfn)
 {
        unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
        unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end));
+       unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
+       unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));
 
        /* Always save lowcore pages (LC protection might be enabled). */
        if (pfn <= LC_PAGES)
@@ -145,6 +144,8 @@ int pfn_is_nosave(unsigned long pfn)
        if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
                return 1;
        /* Skip memory holes and read-only pages (NSS, DCSS, ...). */
+       if (pfn >= stext_pfn && pfn <= eshared_pfn)
+               return ipl_info.type == IPL_TYPE_NSS ? 1 : 0;
        if (tprot(PFN_PHYS(pfn)))
                return 1;
        return 0;
index 6bbd7b5a0bbee36d483e7deba484ce96e3176dfb..0220c2ba75908d11b2b892846231db8bb6d5908a 100644 (file)
@@ -328,6 +328,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
        for (n = mem->count - 1; n > 0 ; n--)
                memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
 
+       memset(&mem->vm[0], 0, sizeof(mem->vm[0]));
        mem->vm[0].cpus_total = cpus;
        mem->vm[0].cpus_configured = cpus;
        mem->vm[0].cpus_standby = 0;
index 416facec4a332eea5c33b6ffad24eb80643b5e2c..d214321db727f8d74f7d55df346ece21e44c7591 100644 (file)
@@ -244,6 +244,12 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
                                do_no_context(regs);
                        else
                                pagefault_out_of_memory();
+               } else if (fault & VM_FAULT_SIGSEGV) {
+                       /* Kernel mode? Handle exceptions or die */
+                       if (!user_mode(regs))
+                               do_no_context(regs);
+                       else
+                               do_sigsegv(regs, SEGV_MAPERR);
                } else if (fault & VM_FAULT_SIGBUS) {
                        /* Kernel mode? Handle exceptions or die */
                        if (!user_mode(regs))
index 52238983527d605914853fd5415ea39617944ffe..6860beb2a280d0a4a65a67c89ad2201b33513068 100644 (file)
@@ -114,6 +114,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 1b6199740e98ab7e554f1676d615983f451e56a7..7a99e6af637284d3061a96a274f375f2189f2eb2 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <asm-generic/sections.h>
 
-extern long __nosave_begin, __nosave_end;
 extern long __machvec_start, __machvec_end;
 extern char __uncached_start, __uncached_end;
 extern char __start_eh_frame[], __stop_eh_frame[];
index 541dc610150888e706977c7944c42ab1d61d7437..a58fec9b55e016df85cdfb7c214cc385e300479c 100644 (file)
@@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
        } else {
                if (fault & VM_FAULT_SIGBUS)
                        do_sigbus(regs, error_code, address);
+               else if (fault & VM_FAULT_SIGSEGV)
+                       bad_area(regs, error_code, address);
                else
                        BUG();
        }
index 59dbd46457250b050ce84a48370a4f96afa3746d..163c7871211095b12d00592b0d373dd67e136d7f 100644 (file)
@@ -252,6 +252,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 3841a081beb3967d9f2f08d0c6d1b4abf5390ff0..ac2db923e51a254a300bc9bd5686200ae4ed08bd 100644 (file)
@@ -443,6 +443,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 42b0b8ce699a94b295e9ec311de1141531275a14..17bd2e167e07edd934dfe9957c43712b21401c55 100644 (file)
@@ -9,11 +9,9 @@
 #include <asm/hibernate.h>
 #include <asm/visasm.h>
 #include <asm/page.h>
+#include <asm/sections.h>
 #include <asm/tlb.h>
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 struct saved_context saved_context;
 
 /*
index 3ff289f422e635cdf74280f86488733c0f88c55f..12b732f593bbceb37b93b7ba9cf6befac1f1707b 100644 (file)
@@ -446,6 +446,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index 5c3aef74237ffda72a0b252d4ee4b118d14a969a..06ab0ebe0a0f39915df14044ac676ef2c9ebf546 100644 (file)
@@ -80,6 +80,8 @@ good_area:
                if (unlikely(fault & VM_FAULT_ERROR)) {
                        if (fault & VM_FAULT_OOM) {
                                goto out_of_memory;
+                       } else if (fault & VM_FAULT_SIGSEGV) {
+                               goto out;
                        } else if (fault & VM_FAULT_SIGBUS) {
                                err = -EACCES;
                                goto out;
index 4dcd34ae194cdc54b772a246706ffa5d7460b3f0..77b522694e744b07c4d49b807ebd4c3551ab0bdd 100644 (file)
@@ -36,8 +36,5 @@ extern int puv3_pm_enter(suspend_state_t state);
 /* Defined in hibernate_asm.S */
 extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist);
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 extern struct pbe *restore_pblist;
 #endif
index d75ef8b6cb5618f28cb2ed0db4192910fcf056e2..9969ec374abb345abcad9ffd5742f155fae36d37 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/sections.h>
 #include <asm/suspend.h>
 
 #include "mach/pm.h"
index af88fa20dbe86bd191a4b1b1a8d2e425aaab9953..ddad189e596e6e33ae618622bc5d4538d0ce20aa 100644 (file)
@@ -2450,7 +2450,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
         * Not recognized on AMD in compat mode (but is recognized in legacy
         * mode).
         */
-       if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
+       if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA)
            && !vendor_intel(ctxt))
                return emulate_ud(ctxt);
 
@@ -2463,25 +2463,13 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        setup_syscalls_segments(ctxt, &cs, &ss);
 
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
-       switch (ctxt->mode) {
-       case X86EMUL_MODE_PROT32:
-               if ((msr_data & 0xfffc) == 0x0)
-                       return emulate_gp(ctxt, 0);
-               break;
-       case X86EMUL_MODE_PROT64:
-               if (msr_data == 0x0)
-                       return emulate_gp(ctxt, 0);
-               break;
-       default:
-               break;
-       }
+       if ((msr_data & 0xfffc) == 0x0)
+               return emulate_gp(ctxt, 0);
 
        ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
-       cs_sel = (u16)msr_data;
-       cs_sel &= ~SELECTOR_RPL_MASK;
+       cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
        ss_sel = cs_sel + 8;
-       ss_sel &= ~SELECTOR_RPL_MASK;
-       if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) {
+       if (efer & EFER_LMA) {
                cs.d = 0;
                cs.l = 1;
        }
@@ -2490,10 +2478,11 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
        ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
-       ctxt->_eip = msr_data;
+       ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data;
 
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
-       *reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
+       *reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
+                                                             (u32)msr_data;
 
        return X86EMUL_CONTINUE;
 }
index d8b1ff68dbb9366692ba2502286172692fb36ef5..e4780b05253109eae4aa4aea6db0fcf5ac7d18ee 100644 (file)
@@ -812,11 +812,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
          unsigned int fault)
 {
        struct task_struct *tsk = current;
-       struct mm_struct *mm = tsk->mm;
        int code = BUS_ADRERR;
 
-       up_read(&mm->mmap_sem);
-
        /* Kernel mode? Handle exceptions or die: */
        if (!(error_code & PF_USER)) {
                no_context(regs, error_code, address, SIGBUS, BUS_ADRERR);
@@ -847,7 +844,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
               unsigned long address, unsigned int fault)
 {
        if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
-               up_read(&current->mm->mmap_sem);
                no_context(regs, error_code, address, 0, 0);
                return;
        }
@@ -855,14 +851,11 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
        if (fault & VM_FAULT_OOM) {
                /* Kernel mode? Handle exceptions or die: */
                if (!(error_code & PF_USER)) {
-                       up_read(&current->mm->mmap_sem);
                        no_context(regs, error_code, address,
                                   SIGSEGV, SEGV_MAPERR);
                        return;
                }
 
-               up_read(&current->mm->mmap_sem);
-
                /*
                 * We ran out of memory, call the OOM killer, and return the
                 * userspace (which will retry the fault, or kill us if we got
@@ -873,6 +866,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
                if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
                             VM_FAULT_HWPOISON_LARGE))
                        do_sigbus(regs, error_code, address, fault);
+               else if (fault & VM_FAULT_SIGSEGV)
+                       bad_area_nosemaphore(regs, error_code, address);
                else
                        BUG();
        }
@@ -1193,6 +1188,7 @@ good_area:
                return;
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
+               up_read(&mm->mmap_sem);
                mm_fault_error(regs, error_code, address, fault);
                return;
        }
index 7d28c885d2385b85c133add5b51176eea8b52af7..291226b952a997f55d3a0be723f15cb9b9b1ab92 100644 (file)
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmzone.h>
+#include <asm/sections.h>
 
 /* Defined in hibernate_asm_32.S */
 extern int restore_image(void);
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 /* Pointer to the temporary resume page tables */
 pgd_t *resume_pg_dir;
 
index a0fde91c16cf779203bcb0195c6f063be9f303b3..8ecaed127634626fa78cc197a08fa7b333f1af66 100644 (file)
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mtrr.h>
+#include <asm/sections.h>
 #include <asm/suspend.h>
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 /* Defined in hibernate_asm_64.S */
 extern int restore_image(void);
 
index 0a1b95f81a32b165ae27421fbddf2423a4da4ca9..2b086a6ae6c74af2216df54ac8c3daed418077cf 100644 (file)
@@ -287,6 +287,36 @@ menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
 
+config XTFPGA_LCD
+       bool "Enable XTFPGA LCD driver"
+       depends on XTENSA_PLATFORM_XTFPGA
+       default n
+       help
+         There's a 2x16 LCD on most of XTFPGA boards, kernel may output
+         progress messages there during bootup/shutdown. It may be useful
+         during board bringup.
+
+         If unsure, say N.
+
+config XTFPGA_LCD_BASE_ADDR
+       hex "XTFPGA LCD base address"
+       depends on XTFPGA_LCD
+       default "0x0d0c0000"
+       help
+         Base address of the LCD controller inside KIO region.
+         Different boards from XTFPGA family have LCD controller at different
+         addresses. Please consult prototyping user guide for your board for
+         the correct address. Wrong address here may lead to hardware lockup.
+
+config XTFPGA_LCD_8BIT_ACCESS
+       bool "Use 8-bit access to XTFPGA LCD"
+       depends on XTFPGA_LCD
+       default n
+       help
+         LCD may be connected with 4- or 8-bit interface, 8-bit access may
+         only be used with 8-bit interface. Please consult prototyping user
+         guide for your board for the correct interface width.
+
 endmenu
 
 source "net/Kconfig"
index 513effd48060743a3b6228b71b4c6703d601fca3..d07c1886bc8f4fbb94f85d5f39474eeda41603db 100644 (file)
@@ -715,7 +715,7 @@ __SYSCALL(323, sys_process_vm_writev, 6)
 __SYSCALL(324, sys_name_to_handle_at, 5)
 #define __NR_open_by_handle_at                 325
 __SYSCALL(325, sys_open_by_handle_at, 3)
-#define __NR_sync_file_range                   326
+#define __NR_sync_file_range2                  326
 __SYSCALL(326, sys_sync_file_range2, 6)
 #define __NR_perf_event_open                   327
 __SYSCALL(327, sys_perf_event_open, 5)
index 70fa7bc42b4a0853012af6f6daaeb254f9c5a086..38278337d85e82690ae143fe038a9f5884eaee21 100644 (file)
@@ -117,6 +117,8 @@ good_area:
        if (unlikely(fault & VM_FAULT_ERROR)) {
                if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
+               else if (fault & VM_FAULT_SIGSEGV)
+                       goto bad_area;
                else if (fault & VM_FAULT_SIGBUS)
                        goto do_sigbus;
                BUG();
index b9ae206340cd51012775e22af3391d3839be985e..7839d38b2337885862df5470e06452ea4efce211 100644 (file)
@@ -6,4 +6,5 @@
 #
 # Note 2! The CFLAGS definitions are in the main makefile...
 
-obj-y                  = setup.o lcd.o
+obj-y                  += setup.o
+obj-$(CONFIG_XTFPGA_LCD) += lcd.o
index 4416773cbde5c1755c17abf3d5028babaf80ef6c..b39fbcf5c611614009ac303177070bd551afc0e3 100644 (file)
@@ -44,9 +44,6 @@
 
 /* UART */
 #define DUART16552_PADDR       (XCHAL_KIO_PADDR + 0x0D050020)
-/* LCD instruction and data addresses. */
-#define LCD_INSTR_ADDR         ((char *)IOADDR(0x0D040000))
-#define LCD_DATA_ADDR          ((char *)IOADDR(0x0D040004))
 
 /* Misc. */
 #define XTFPGA_FPGAREGS_VADDR  IOADDR(0x0D020000)
index 0e435645af5a1ed2043944b6d6fa46647a7a3d86..4c8541ed11396e52bd570cb2cbd0d7bda1782f00 100644 (file)
 #ifndef __XTENSA_XTAVNET_LCD_H
 #define __XTENSA_XTAVNET_LCD_H
 
+#ifdef CONFIG_XTFPGA_LCD
 /* Display string STR at position POS on the LCD. */
 void lcd_disp_at_pos(char *str, unsigned char pos);
 
 /* Shift the contents of the LCD display left or right. */
 void lcd_shiftleft(void);
 void lcd_shiftright(void);
+#else
+static inline void lcd_disp_at_pos(char *str, unsigned char pos)
+{
+}
+
+static inline void lcd_shiftleft(void)
+{
+}
+
+static inline void lcd_shiftright(void)
+{
+}
+#endif
+
 #endif
index 2872301598df266ffe2822f9eb782b0e23b7156c..4dc0c1b43f4bfd917a65fc04b225a790d0fdfeaa 100644 (file)
@@ -1,50 +1,63 @@
 /*
- * Driver for the LCD display on the Tensilica LX60 Board.
+ * Driver for the LCD display on the Tensilica XTFPGA board family.
+ * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * Copyright (C) 2001, 2006 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
  */
 
-/*
- *
- * FIXME: this code is from the examples from the LX60 user guide.
- *
- * The lcd_pause function does busy waiting, which is probably not
- * great. Maybe the code could be changed to use kernel timers, or
- * change the hardware to not need to wait.
- */
-
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
 
 #include <platform/hardware.h>
 #include <platform/lcd.h>
-#include <linux/delay.h>
 
-#define LCD_PAUSE_ITERATIONS   4000
+/* LCD instruction and data addresses. */
+#define LCD_INSTR_ADDR         ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR))
+#define LCD_DATA_ADDR          (LCD_INSTR_ADDR + 4)
+
 #define LCD_CLEAR              0x1
 #define LCD_DISPLAY_ON         0xc
 
 /* 8bit and 2 lines display */
 #define LCD_DISPLAY_MODE8BIT   0x38
+#define LCD_DISPLAY_MODE4BIT   0x28
 #define LCD_DISPLAY_POS                0x80
 #define LCD_SHIFT_LEFT         0x18
 #define LCD_SHIFT_RIGHT                0x1c
 
+static void lcd_put_byte(u8 *addr, u8 data)
+{
+#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS
+       ACCESS_ONCE(*addr) = data;
+#else
+       ACCESS_ONCE(*addr) = data & 0xf0;
+       ACCESS_ONCE(*addr) = (data << 4) & 0xf0;
+#endif
+}
+
 static int __init lcd_init(void)
 {
-       *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
        mdelay(5);
-       *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
        udelay(200);
-       *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
+       udelay(50);
+#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS
+       ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT;
+       udelay(50);
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT);
        udelay(50);
-       *LCD_INSTR_ADDR = LCD_DISPLAY_ON;
+#endif
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON);
        udelay(50);
-       *LCD_INSTR_ADDR = LCD_CLEAR;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR);
        mdelay(10);
        lcd_disp_at_pos("XTENSA LINUX", 0);
        return 0;
@@ -52,10 +65,10 @@ static int __init lcd_init(void)
 
 void lcd_disp_at_pos(char *str, unsigned char pos)
 {
-       *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos);
        udelay(100);
        while (*str != 0) {
-               *LCD_DATA_ADDR = *str;
+               lcd_put_byte(LCD_DATA_ADDR, *str);
                udelay(200);
                str++;
        }
@@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned char pos)
 
 void lcd_shiftleft(void)
 {
-       *LCD_INSTR_ADDR = LCD_SHIFT_LEFT;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT);
        udelay(50);
 }
 
 void lcd_shiftright(void)
 {
-       *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT;
+       lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT);
        udelay(50);
 }
 
index ee6367b8eaf7afcf6866ff75193e5ca59bfa94f4..e9b13b92ba1e8d197eb9556864231ecc7d565cfd 100644 (file)
@@ -539,8 +539,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
                return_ACPI_STATUS(AE_NOT_EXIST);
        }
 
-       obj_desc->region.address =
-           (acpi_physical_address) ACPI_TO_INTEGER(table);
+       obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
        obj_desc->region.length = table->length;
 
        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
index e57cd38004e33c3adb3b7850bc25b4f23f577430..0d2351596a3c5a019f638fccc8efb77472cfb213 100644 (file)
@@ -301,8 +301,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
                        ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
                                        "%4.4s %p Attempted physical table override failed",
                                        table_header->signature,
-                                       ACPI_CAST_PTR(void,
-                                                     table_desc->address)));
+                                       ACPI_PHYSADDR_TO_PTR(table_desc->address)));
                        return (NULL);
                }
 
@@ -318,7 +317,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
        ACPI_INFO((AE_INFO,
                   "%4.4s %p %s table override, new table: %p",
                   table_header->signature,
-                  ACPI_CAST_PTR(void, table_desc->address),
+                  ACPI_PHYSADDR_TO_PTR(table_desc->address),
                   override_type, new_table));
 
        /* We can now unmap/delete the original table (if fully mapped) */
index 7c2ecfb7c2c37dbb448e7703d2689d994fe8931f..e12486031d9716eefdc920826644656404e1dd81 100644 (file)
@@ -118,7 +118,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
  *
  ******************************************************************************/
 
-acpi_status acpi_find_root_pointer(acpi_size *table_address)
+acpi_status acpi_find_root_pointer(acpi_physical_address * table_address)
 {
        u8 *table_ptr;
        u8 *mem_rover;
@@ -176,7 +176,8 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
                        physical_address +=
                            (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 
-                       *table_address = physical_address;
+                       *table_address =
+                           (acpi_physical_address) physical_address;
                        return_ACPI_STATUS(AE_OK);
                }
        }
@@ -209,7 +210,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
                    (ACPI_HI_RSDP_WINDOW_BASE +
                     ACPI_PTR_DIFF(mem_rover, table_ptr));
 
-               *table_address = physical_address;
+               *table_address = (acpi_physical_address) physical_address;
                return_ACPI_STATUS(AE_OK);
        }
 
index a88894190e419eb697a3546170ca0652bb8f8db3..c991fe680e589efd30e3cfc3419ee9f8e0f6ea4f 100644 (file)
@@ -978,7 +978,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
                return -EINVAL;
 
        drv->safe_state_index = -1;
-       for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
+       for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
                drv->states[i].name[0] = '\0';
                drv->states[i].desc[0] = '\0';
        }
index b81ddfea1da075ad3c1d0cbeb9ab7bf854593436..9da952c9af9131169184deeb000df1d934548a43 100644 (file)
@@ -105,6 +105,8 @@ source "drivers/block/paride/Kconfig"
 
 source "drivers/block/mtip32xx/Kconfig"
 
+source "drivers/block/zram/Kconfig"
+
 config BLK_CPQ_DA
        tristate "Compaq SMART2 support"
        depends on PCI && VIRT_TO_BUS
index ca07399a8d99efb2d11b80bc266c52c496c902e3..3675937ab651afc8df72448cc56ee8bfe15d7b96 100644 (file)
@@ -41,6 +41,7 @@ obj-$(CONFIG_BLK_DEV_RBD)     += rbd.o
 obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/
 
 obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/
+obj-$(CONFIG_ZRAM) += zram/
 
 nvme-y         := nvme-core.o nvme-scsi.o
 swim_mod-y     := swim.o swim_asm.o
index cf1576d5436369d345465db37cd8368a80eff605..a5c987ae665d68ed9773cd1340aa56d98a647e05 100644 (file)
@@ -815,10 +815,6 @@ static int __init nbd_init(void)
                return -EINVAL;
        }
 
-       nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
-       if (!nbd_dev)
-               return -ENOMEM;
-
        part_shift = 0;
        if (max_part > 0) {
                part_shift = fls(max_part);
@@ -840,6 +836,10 @@ static int __init nbd_init(void)
        if (nbds_max > 1UL << (MINORBITS - part_shift))
                return -EINVAL;
 
+       nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
+       if (!nbd_dev)
+               return -ENOMEM;
+
        for (i = 0; i < nbds_max; i++) {
                struct gendisk *disk = alloc_disk(1 << part_shift);
                if (!disk)
index 7e3f45105f1189b13c87f7fafa8e35da127327e2..dd297099c99dd1ee93980934652d7498666a4b10 100644 (file)
@@ -2115,6 +2115,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
                        result, xferred);
                if (!img_request->result)
                        img_request->result = result;
+               /*
+                * Need to end I/O on the entire obj_request worth of
+                * bytes in case of error.
+                */
+               xferred = obj_request->length;
        }
 
        /* Image object requests don't own their page array */
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
new file mode 100644 (file)
index 0000000..6489c0f
--- /dev/null
@@ -0,0 +1,34 @@
+config ZRAM
+       tristate "Compressed RAM block device support"
+       depends on BLOCK && SYSFS && ZSMALLOC
+       select LZO_COMPRESS
+       select LZO_DECOMPRESS
+       default n
+       help
+         Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
+         Pages written to these disks are compressed and stored in memory
+         itself. These disks allow very fast I/O and compression provides
+         good amounts of memory savings.
+
+         It has several use cases, for example: /tmp storage, use as swap
+         disks and maybe many more.
+
+         See zram.txt for more information.
+
+config ZRAM_LZ4_COMPRESS
+       bool "Enable LZ4 algorithm support"
+       depends on ZRAM
+       select LZ4_COMPRESS
+       select LZ4_DECOMPRESS
+       default n
+       help
+         This option enables LZ4 compression algorithm support. Compression
+         algorithm can be changed using `comp_algorithm' device attribute.
+
+config ZRAM_DEBUG
+       bool "Compressed RAM block device debug support"
+       depends on ZRAM
+       default n
+       help
+         This option adds additional debugging code to the compressed
+         RAM block device driver.
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
new file mode 100644 (file)
index 0000000..be0763f
--- /dev/null
@@ -0,0 +1,5 @@
+zram-y :=      zcomp_lzo.o zcomp.o zram_drv.o
+
+zram-$(CONFIG_ZRAM_LZ4_COMPRESS) += zcomp_lz4.o
+
+obj-$(CONFIG_ZRAM)     +=      zram.o
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
new file mode 100644 (file)
index 0000000..f1ff39a
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include "zcomp.h"
+#include "zcomp_lzo.h"
+#ifdef CONFIG_ZRAM_LZ4_COMPRESS
+#include "zcomp_lz4.h"
+#endif
+
+/*
+ * single zcomp_strm backend
+ */
+struct zcomp_strm_single {
+       struct mutex strm_lock;
+       struct zcomp_strm *zstrm;
+};
+
+/*
+ * multi zcomp_strm backend
+ */
+struct zcomp_strm_multi {
+       /* protect strm list */
+       spinlock_t strm_lock;
+       /* max possible number of zstrm streams */
+       int max_strm;
+       /* number of available zstrm streams */
+       int avail_strm;
+       /* list of available strms */
+       struct list_head idle_strm;
+       wait_queue_head_t strm_wait;
+};
+
+static struct zcomp_backend *backends[] = {
+       &zcomp_lzo,
+#ifdef CONFIG_ZRAM_LZ4_COMPRESS
+       &zcomp_lz4,
+#endif
+       NULL
+};
+
+static struct zcomp_backend *find_backend(const char *compress)
+{
+       int i = 0;
+       while (backends[i]) {
+               if (sysfs_streq(compress, backends[i]->name))
+                       break;
+               i++;
+       }
+       return backends[i];
+}
+
+static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+       if (zstrm->private)
+               comp->backend->destroy(zstrm->private);
+       free_pages((unsigned long)zstrm->buffer, 1);
+       kfree(zstrm);
+}
+
+/*
+ * allocate new zcomp_strm structure with ->private initialized by
+ * backend, return NULL on error
+ */
+static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
+{
+       struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
+       if (!zstrm)
+               return NULL;
+
+       zstrm->private = comp->backend->create();
+       /*
+        * allocate 2 pages. 1 for compressed data, plus 1 extra for the
+        * case when compressed size is larger than the original one
+        */
+       zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
+       if (!zstrm->private || !zstrm->buffer) {
+               zcomp_strm_free(comp, zstrm);
+               zstrm = NULL;
+       }
+       return zstrm;
+}
+
+/*
+ * get idle zcomp_strm or wait until other process release
+ * (zcomp_strm_release()) one for us
+ */
+static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp)
+{
+       struct zcomp_strm_multi *zs = comp->stream;
+       struct zcomp_strm *zstrm;
+
+       while (1) {
+               spin_lock(&zs->strm_lock);
+               if (!list_empty(&zs->idle_strm)) {
+                       zstrm = list_entry(zs->idle_strm.next,
+                                       struct zcomp_strm, list);
+                       list_del(&zstrm->list);
+                       spin_unlock(&zs->strm_lock);
+                       return zstrm;
+               }
+               /* zstrm streams limit reached, wait for idle stream */
+               if (zs->avail_strm >= zs->max_strm) {
+                       spin_unlock(&zs->strm_lock);
+                       wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
+                       continue;
+               }
+               /* allocate new zstrm stream */
+               zs->avail_strm++;
+               spin_unlock(&zs->strm_lock);
+
+               zstrm = zcomp_strm_alloc(comp);
+               if (!zstrm) {
+                       spin_lock(&zs->strm_lock);
+                       zs->avail_strm--;
+                       spin_unlock(&zs->strm_lock);
+                       wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
+                       continue;
+               }
+               break;
+       }
+       return zstrm;
+}
+
+/* add stream back to idle list and wake up waiter or free the stream */
+static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+       struct zcomp_strm_multi *zs = comp->stream;
+
+       spin_lock(&zs->strm_lock);
+       if (zs->avail_strm <= zs->max_strm) {
+               list_add(&zstrm->list, &zs->idle_strm);
+               spin_unlock(&zs->strm_lock);
+               wake_up(&zs->strm_wait);
+               return;
+       }
+
+       zs->avail_strm--;
+       spin_unlock(&zs->strm_lock);
+       zcomp_strm_free(comp, zstrm);
+}
+
+/* change max_strm limit */
+static bool zcomp_strm_multi_set_max_streams(struct zcomp *comp, int num_strm)
+{
+       struct zcomp_strm_multi *zs = comp->stream;
+       struct zcomp_strm *zstrm;
+
+       spin_lock(&zs->strm_lock);
+       zs->max_strm = num_strm;
+       /*
+        * if user has lowered the limit and there are idle streams,
+        * immediately free as much streams (and memory) as we can.
+        */
+       while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) {
+               zstrm = list_entry(zs->idle_strm.next,
+                               struct zcomp_strm, list);
+               list_del(&zstrm->list);
+               zcomp_strm_free(comp, zstrm);
+               zs->avail_strm--;
+       }
+       spin_unlock(&zs->strm_lock);
+       return true;
+}
+
+static void zcomp_strm_multi_destroy(struct zcomp *comp)
+{
+       struct zcomp_strm_multi *zs = comp->stream;
+       struct zcomp_strm *zstrm;
+
+       while (!list_empty(&zs->idle_strm)) {
+               zstrm = list_entry(zs->idle_strm.next,
+                               struct zcomp_strm, list);
+               list_del(&zstrm->list);
+               zcomp_strm_free(comp, zstrm);
+       }
+       kfree(zs);
+}
+
+static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm)
+{
+       struct zcomp_strm *zstrm;
+       struct zcomp_strm_multi *zs;
+
+       comp->destroy = zcomp_strm_multi_destroy;
+       comp->strm_find = zcomp_strm_multi_find;
+       comp->strm_release = zcomp_strm_multi_release;
+       comp->set_max_streams = zcomp_strm_multi_set_max_streams;
+       zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL);
+       if (!zs)
+               return -ENOMEM;
+
+       comp->stream = zs;
+       spin_lock_init(&zs->strm_lock);
+       INIT_LIST_HEAD(&zs->idle_strm);
+       init_waitqueue_head(&zs->strm_wait);
+       zs->max_strm = max_strm;
+       zs->avail_strm = 1;
+
+       zstrm = zcomp_strm_alloc(comp);
+       if (!zstrm) {
+               kfree(zs);
+               return -ENOMEM;
+       }
+       list_add(&zstrm->list, &zs->idle_strm);
+       return 0;
+}
+
+static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp)
+{
+       struct zcomp_strm_single *zs = comp->stream;
+       mutex_lock(&zs->strm_lock);
+       return zs->zstrm;
+}
+
+static void zcomp_strm_single_release(struct zcomp *comp,
+               struct zcomp_strm *zstrm)
+{
+       struct zcomp_strm_single *zs = comp->stream;
+       mutex_unlock(&zs->strm_lock);
+}
+
+static bool zcomp_strm_single_set_max_streams(struct zcomp *comp, int num_strm)
+{
+       /* zcomp_strm_single support only max_comp_streams == 1 */
+       return false;
+}
+
+static void zcomp_strm_single_destroy(struct zcomp *comp)
+{
+       struct zcomp_strm_single *zs = comp->stream;
+       zcomp_strm_free(comp, zs->zstrm);
+       kfree(zs);
+}
+
+static int zcomp_strm_single_create(struct zcomp *comp)
+{
+       struct zcomp_strm_single *zs;
+
+       comp->destroy = zcomp_strm_single_destroy;
+       comp->strm_find = zcomp_strm_single_find;
+       comp->strm_release = zcomp_strm_single_release;
+       comp->set_max_streams = zcomp_strm_single_set_max_streams;
+       zs = kmalloc(sizeof(struct zcomp_strm_single), GFP_KERNEL);
+       if (!zs)
+               return -ENOMEM;
+
+       comp->stream = zs;
+       mutex_init(&zs->strm_lock);
+       zs->zstrm = zcomp_strm_alloc(comp);
+       if (!zs->zstrm) {
+               kfree(zs);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+/* show available compressors */
+ssize_t zcomp_available_show(const char *comp, char *buf)
+{
+       ssize_t sz = 0;
+       int i = 0;
+
+       while (backends[i]) {
+               if (sysfs_streq(comp, backends[i]->name))
+                       sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
+                                       "[%s] ", backends[i]->name);
+               else
+                       sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
+                                       "%s ", backends[i]->name);
+               i++;
+       }
+       sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
+       return sz;
+}
+
+bool zcomp_set_max_streams(struct zcomp *comp, int num_strm)
+{
+       return comp->set_max_streams(comp, num_strm);
+}
+
+struct zcomp_strm *zcomp_strm_find(struct zcomp *comp)
+{
+       return comp->strm_find(comp);
+}
+
+void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm)
+{
+       comp->strm_release(comp, zstrm);
+}
+
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+               const unsigned char *src, size_t *dst_len)
+{
+       return comp->backend->compress(src, zstrm->buffer, dst_len,
+                       zstrm->private);
+}
+
+int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
+               size_t src_len, unsigned char *dst)
+{
+       return comp->backend->decompress(src, src_len, dst);
+}
+
+void zcomp_destroy(struct zcomp *comp)
+{
+       comp->destroy(comp);
+       kfree(comp);
+}
+
+/*
+ * search available compressors for requested algorithm.
+ * allocate new zcomp and initialize it. return compressing
+ * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
+ * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
+ * case of allocation error.
+ */
+struct zcomp *zcomp_create(const char *compress, int max_strm)
+{
+       struct zcomp *comp;
+       struct zcomp_backend *backend;
+
+       backend = find_backend(compress);
+       if (!backend)
+               return ERR_PTR(-EINVAL);
+
+       comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
+       if (!comp)
+               return ERR_PTR(-ENOMEM);
+
+       comp->backend = backend;
+       if (max_strm > 1)
+               zcomp_strm_multi_create(comp, max_strm);
+       else
+               zcomp_strm_single_create(comp);
+       if (!comp->stream) {
+               kfree(comp);
+               return ERR_PTR(-ENOMEM);
+       }
+       return comp;
+}
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
new file mode 100644 (file)
index 0000000..c59d1fc
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ZCOMP_H_
+#define _ZCOMP_H_
+
+#include <linux/mutex.h>
+
+struct zcomp_strm {
+       /* compression/decompression buffer */
+       void *buffer;
+       /*
+        * The private data of the compression stream, only compression
+        * stream backend can touch this (e.g. compression algorithm
+        * working memory)
+        */
+       void *private;
+       /* used in multi stream backend, protected by backend strm_lock */
+       struct list_head list;
+};
+
+/* static compression backend */
+struct zcomp_backend {
+       int (*compress)(const unsigned char *src, unsigned char *dst,
+                       size_t *dst_len, void *private);
+
+       int (*decompress)(const unsigned char *src, size_t src_len,
+                       unsigned char *dst);
+
+       void *(*create)(void);
+       void (*destroy)(void *private);
+
+       const char *name;
+};
+
+/* dynamic per-device compression frontend */
+struct zcomp {
+       void *stream;
+       struct zcomp_backend *backend;
+
+       struct zcomp_strm *(*strm_find)(struct zcomp *comp);
+       void (*strm_release)(struct zcomp *comp, struct zcomp_strm *zstrm);
+       bool (*set_max_streams)(struct zcomp *comp, int num_strm);
+       void (*destroy)(struct zcomp *comp);
+};
+
+ssize_t zcomp_available_show(const char *comp, char *buf);
+
+struct zcomp *zcomp_create(const char *comp, int max_strm);
+void zcomp_destroy(struct zcomp *comp);
+
+struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
+void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm);
+
+int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
+               const unsigned char *src, size_t *dst_len);
+
+int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
+               size_t src_len, unsigned char *dst);
+
+bool zcomp_set_max_streams(struct zcomp *comp, int num_strm);
+#endif /* _ZCOMP_H_ */
diff --git a/drivers/block/zram/zcomp_lz4.c b/drivers/block/zram/zcomp_lz4.c
new file mode 100644 (file)
index 0000000..f2afb7e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/lz4.h>
+
+#include "zcomp_lz4.h"
+
+static void *zcomp_lz4_create(void)
+{
+       return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void zcomp_lz4_destroy(void *private)
+{
+       kfree(private);
+}
+
+static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
+               size_t *dst_len, void *private)
+{
+       /* return  : Success if return 0 */
+       return lz4_compress(src, PAGE_SIZE, dst, dst_len, private);
+}
+
+static int zcomp_lz4_decompress(const unsigned char *src, size_t src_len,
+               unsigned char *dst)
+{
+       size_t dst_len = PAGE_SIZE;
+       /* return  : Success if return 0 */
+       return lz4_decompress_unknownoutputsize(src, src_len, dst, &dst_len);
+}
+
+struct zcomp_backend zcomp_lz4 = {
+       .compress = zcomp_lz4_compress,
+       .decompress = zcomp_lz4_decompress,
+       .create = zcomp_lz4_create,
+       .destroy = zcomp_lz4_destroy,
+       .name = "lz4",
+};
diff --git a/drivers/block/zram/zcomp_lz4.h b/drivers/block/zram/zcomp_lz4.h
new file mode 100644 (file)
index 0000000..60613fb
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ZCOMP_LZ4_H_
+#define _ZCOMP_LZ4_H_
+
+#include "zcomp.h"
+
+extern struct zcomp_backend zcomp_lz4;
+
+#endif /* _ZCOMP_LZ4_H_ */
diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c
new file mode 100644 (file)
index 0000000..da1bc47
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/lzo.h>
+
+#include "zcomp_lzo.h"
+
+static void *lzo_create(void)
+{
+       return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+}
+
+static void lzo_destroy(void *private)
+{
+       kfree(private);
+}
+
+static int lzo_compress(const unsigned char *src, unsigned char *dst,
+               size_t *dst_len, void *private)
+{
+       int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private);
+       return ret == LZO_E_OK ? 0 : ret;
+}
+
+static int lzo_decompress(const unsigned char *src, size_t src_len,
+               unsigned char *dst)
+{
+       size_t dst_len = PAGE_SIZE;
+       int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
+       return ret == LZO_E_OK ? 0 : ret;
+}
+
+struct zcomp_backend zcomp_lzo = {
+       .compress = lzo_compress,
+       .decompress = lzo_decompress,
+       .create = lzo_create,
+       .destroy = lzo_destroy,
+       .name = "lzo",
+};
diff --git a/drivers/block/zram/zcomp_lzo.h b/drivers/block/zram/zcomp_lzo.h
new file mode 100644 (file)
index 0000000..128c580
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014 Sergey Senozhatsky.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ZCOMP_LZO_H_
+#define _ZCOMP_LZO_H_
+
+#include "zcomp.h"
+
+extern struct zcomp_backend zcomp_lzo;
+
+#endif /* _ZCOMP_LZO_H_ */
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
new file mode 100644 (file)
index 0000000..45e2e85
--- /dev/null
@@ -0,0 +1,1162 @@
+/*
+ * Compressed RAM block device
+ *
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
+ *               2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+#define KMSG_COMPONENT "zram"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#ifdef CONFIG_ZRAM_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bio.h>
+#include <linux/bitops.h>
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+#include <linux/device.h>
+#include <linux/genhd.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/err.h>
+
+#include "zram_drv.h"
+
+/* Globals */
+static int zram_major;
+static struct zram *zram_devices;
+static const char *default_compressor = "lzo";
+
+/* Module params (documentation at end) */
+static unsigned int num_devices = 1;
+
+#define ZRAM_ATTR_RO(name)                                             \
+static ssize_t zram_attr_##name##_show(struct device *d,               \
+                               struct device_attribute *attr, char *b) \
+{                                                                      \
+       struct zram *zram = dev_to_zram(d);                             \
+       return scnprintf(b, PAGE_SIZE, "%llu\n",                        \
+               (u64)atomic64_read(&zram->stats.name));                 \
+}                                                                      \
+static struct device_attribute dev_attr_##name =                       \
+       __ATTR(name, S_IRUGO, zram_attr_##name##_show, NULL);
+
+static inline int init_done(struct zram *zram)
+{
+       return zram->meta != NULL;
+}
+
+static inline struct zram *dev_to_zram(struct device *dev)
+{
+       return (struct zram *)dev_to_disk(dev)->private_data;
+}
+
+static ssize_t disksize_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct zram *zram = dev_to_zram(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize);
+}
+
+static ssize_t initstate_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u32 val;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       val = init_done(zram);
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n", val);
+}
+
+static ssize_t orig_data_size_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct zram *zram = dev_to_zram(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n",
+               (u64)(atomic64_read(&zram->stats.pages_stored)) << PAGE_SHIFT);
+}
+
+static ssize_t mem_used_total_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u64 val = 0;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       if (init_done(zram)) {
+               struct zram_meta *meta = zram->meta;
+               val = zs_get_total_pages(meta->mem_pool);
+       }
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
+}
+
+static ssize_t max_comp_streams_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       int val;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       val = zram->max_comp_streams;
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t mem_limit_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u64 val;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       val = zram->limit_pages;
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
+}
+
+static ssize_t mem_limit_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       u64 limit;
+       char *tmp;
+       struct zram *zram = dev_to_zram(dev);
+
+       limit = memparse(buf, &tmp);
+       if (buf == tmp) /* no chars parsed, invalid input */
+               return -EINVAL;
+
+       down_write(&zram->init_lock);
+       zram->limit_pages = PAGE_ALIGN(limit) >> PAGE_SHIFT;
+       up_write(&zram->init_lock);
+
+       return len;
+}
+
+static ssize_t mem_used_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       u64 val = 0;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       if (init_done(zram))
+               val = atomic_long_read(&zram->stats.max_used_pages);
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
+}
+
+static ssize_t mem_used_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       int err;
+       unsigned long val;
+       struct zram *zram = dev_to_zram(dev);
+
+       err = kstrtoul(buf, 10, &val);
+       if (err || val != 0)
+               return -EINVAL;
+
+       down_read(&zram->init_lock);
+       if (init_done(zram)) {
+               struct zram_meta *meta = zram->meta;
+               atomic_long_set(&zram->stats.max_used_pages,
+                               zs_get_total_pages(meta->mem_pool));
+       }
+       up_read(&zram->init_lock);
+
+       return len;
+}
+
+static ssize_t max_comp_streams_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       int num;
+       struct zram *zram = dev_to_zram(dev);
+       int ret;
+
+       ret = kstrtoint(buf, 0, &num);
+       if (ret < 0)
+               return ret;
+       if (num < 1)
+               return -EINVAL;
+
+       down_write(&zram->init_lock);
+       if (init_done(zram)) {
+               if (!zcomp_set_max_streams(zram->comp, num)) {
+                       pr_info("Cannot change max compression streams\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
+       zram->max_comp_streams = num;
+       ret = len;
+out:
+       up_write(&zram->init_lock);
+       return ret;
+}
+
+static ssize_t comp_algorithm_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       size_t sz;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       sz = zcomp_available_show(zram->compressor, buf);
+       up_read(&zram->init_lock);
+
+       return sz;
+}
+
+static ssize_t comp_algorithm_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       struct zram *zram = dev_to_zram(dev);
+       down_write(&zram->init_lock);
+       if (init_done(zram)) {
+               up_write(&zram->init_lock);
+               pr_info("Can't change algorithm for initialized device\n");
+               return -EBUSY;
+       }
+       strlcpy(zram->compressor, buf, sizeof(zram->compressor));
+       up_write(&zram->init_lock);
+       return len;
+}
+
+/* flag operations needs meta->tb_lock */
+static int zram_test_flag(struct zram_meta *meta, u32 index,
+                       enum zram_pageflags flag)
+{
+       return meta->table[index].value & BIT(flag);
+}
+
+static void zram_set_flag(struct zram_meta *meta, u32 index,
+                       enum zram_pageflags flag)
+{
+       meta->table[index].value |= BIT(flag);
+}
+
+static void zram_clear_flag(struct zram_meta *meta, u32 index,
+                       enum zram_pageflags flag)
+{
+       meta->table[index].value &= ~BIT(flag);
+}
+
+static size_t zram_get_obj_size(struct zram_meta *meta, u32 index)
+{
+       return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1);
+}
+
+static void zram_set_obj_size(struct zram_meta *meta,
+                                       u32 index, size_t size)
+{
+       unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT;
+
+       meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size;
+}
+
+static inline int is_partial_io(struct bio_vec *bvec)
+{
+       return bvec->bv_len != PAGE_SIZE;
+}
+
+/*
+ * Check if request is within bounds and aligned on zram logical blocks.
+ */
+static inline int valid_io_request(struct zram *zram, struct bio *bio)
+{
+       u64 start, end, bound;
+
+       /* unaligned request */
+       if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
+               return 0;
+       if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
+               return 0;
+
+       start = bio->bi_sector;
+       end = start + (bio->bi_size >> SECTOR_SHIFT);
+       bound = zram->disksize >> SECTOR_SHIFT;
+       /* out of range range */
+       if (unlikely(start >= bound || end >= bound || start > end))
+               return 0;
+
+       /* I/O request is valid */
+       return 1;
+}
+
+static void zram_meta_free(struct zram_meta *meta, u64 disksize)
+{
+       size_t num_pages = disksize >> PAGE_SHIFT;
+       size_t index;
+
+       /* Free all pages that are still in this zram device */
+       for (index = 0; index < num_pages; index++) {
+               unsigned long handle = meta->table[index].handle;
+
+               if (!handle)
+                       continue;
+
+               zs_free(meta->mem_pool, handle);
+       }
+
+       zs_destroy_pool(meta->mem_pool);
+       vfree(meta->table);
+       kfree(meta);
+}
+
+static struct zram_meta *zram_meta_alloc(u64 disksize)
+{
+       size_t num_pages;
+       struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
+       if (!meta)
+               goto out;
+
+       num_pages = disksize >> PAGE_SHIFT;
+       meta->table = vzalloc(num_pages * sizeof(*meta->table));
+       if (!meta->table) {
+               pr_err("Error allocating zram address table\n");
+               goto free_meta;
+       }
+
+       meta->mem_pool = zs_create_pool(GFP_NOIO | __GFP_HIGHMEM);
+       if (!meta->mem_pool) {
+               pr_err("Error creating memory pool\n");
+               goto free_table;
+       }
+
+       return meta;
+
+free_table:
+       vfree(meta->table);
+free_meta:
+       kfree(meta);
+       meta = NULL;
+out:
+       return meta;
+}
+
+static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
+{
+       if (*offset + bvec->bv_len >= PAGE_SIZE)
+               (*index)++;
+       *offset = (*offset + bvec->bv_len) % PAGE_SIZE;
+}
+
+static int page_zero_filled(void *ptr)
+{
+       unsigned int pos;
+       unsigned long *page;
+
+       page = (unsigned long *)ptr;
+
+       for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
+               if (page[pos])
+                       return 0;
+       }
+
+       return 1;
+}
+
+static void handle_zero_page(struct bio_vec *bvec)
+{
+       struct page *page = bvec->bv_page;
+       void *user_mem;
+
+       user_mem = kmap_atomic(page);
+       if (is_partial_io(bvec))
+               memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
+       else
+               clear_page(user_mem);
+       kunmap_atomic(user_mem);
+
+       flush_dcache_page(page);
+}
+
+
+/*
+ * To protect concurrent access to the same index entry,
+ * caller should hold this table index entry's bit_spinlock to
+ * indicate this index entry is accessing.
+ */
+static void zram_free_page(struct zram *zram, size_t index)
+{
+       struct zram_meta *meta = zram->meta;
+       unsigned long handle = meta->table[index].handle;
+
+       if (unlikely(!handle)) {
+               /*
+                * No memory is allocated for zero filled pages.
+                * Simply clear zero page flag.
+                */
+               if (zram_test_flag(meta, index, ZRAM_ZERO)) {
+                       zram_clear_flag(meta, index, ZRAM_ZERO);
+                       atomic64_dec(&zram->stats.zero_pages);
+               }
+               return;
+       }
+
+       zs_free(meta->mem_pool, handle);
+
+       atomic64_sub(zram_get_obj_size(meta, index),
+                       &zram->stats.compr_data_size);
+       atomic64_dec(&zram->stats.pages_stored);
+
+       meta->table[index].handle = 0;
+       zram_set_obj_size(meta, index, 0);
+}
+
+static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
+{
+       int ret = 0;
+       unsigned char *cmem;
+       struct zram_meta *meta = zram->meta;
+       unsigned long handle;
+       size_t size;
+
+       bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+       handle = meta->table[index].handle;
+       size = zram_get_obj_size(meta, index);
+
+       if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) {
+               bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+               clear_page(mem);
+               return 0;
+       }
+
+       cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO);
+       if (size == PAGE_SIZE)
+               copy_page(mem, cmem);
+       else
+               ret = zcomp_decompress(zram->comp, cmem, size, mem);
+       zs_unmap_object(meta->mem_pool, handle);
+       bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+       /* Should NEVER happen. Return bio error if it does. */
+       if (unlikely(ret)) {
+               pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+                         u32 index, int offset, struct bio *bio)
+{
+       int ret;
+       struct page *page;
+       unsigned char *user_mem, *uncmem = NULL;
+       struct zram_meta *meta = zram->meta;
+       page = bvec->bv_page;
+
+       bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+       if (unlikely(!meta->table[index].handle) ||
+                       zram_test_flag(meta, index, ZRAM_ZERO)) {
+               bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+               handle_zero_page(bvec);
+               return 0;
+       }
+       bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+       if (is_partial_io(bvec))
+               /* Use  a temporary buffer to decompress the page */
+               uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+
+       user_mem = kmap_atomic(page);
+       if (!is_partial_io(bvec))
+               uncmem = user_mem;
+
+       if (!uncmem) {
+               pr_info("Unable to allocate temp memory\n");
+               ret = -ENOMEM;
+               goto out_cleanup;
+       }
+
+       ret = zram_decompress_page(zram, uncmem, index);
+       /* Should NEVER happen. Return bio error if it does. */
+       if (unlikely(ret))
+               goto out_cleanup;
+
+       if (is_partial_io(bvec))
+               memcpy(user_mem + bvec->bv_offset, uncmem + offset,
+                               bvec->bv_len);
+
+       flush_dcache_page(page);
+       ret = 0;
+out_cleanup:
+       kunmap_atomic(user_mem);
+       if (is_partial_io(bvec))
+               kfree(uncmem);
+       return ret;
+}
+
+static inline void update_used_max(struct zram *zram,
+                                       const unsigned long pages)
+{
+       int old_max, cur_max;
+
+       old_max = atomic_long_read(&zram->stats.max_used_pages);
+
+       do {
+               cur_max = old_max;
+               if (pages > cur_max)
+                       old_max = atomic_long_cmpxchg(
+                               &zram->stats.max_used_pages, cur_max, pages);
+       } while (old_max != cur_max);
+}
+
+static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
+                          int offset)
+{
+       int ret = 0;
+       size_t clen;
+       unsigned long handle;
+       struct page *page;
+       unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
+       struct zram_meta *meta = zram->meta;
+       struct zcomp_strm *zstrm;
+       bool locked = false;
+       unsigned long alloced_pages;
+
+       page = bvec->bv_page;
+       if (is_partial_io(bvec)) {
+               /*
+                * This is a partial IO. We need to read the full page
+                * before to write the changes.
+                */
+               uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+               if (!uncmem) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               ret = zram_decompress_page(zram, uncmem, index);
+               if (ret)
+                       goto out;
+       }
+
+       zstrm = zcomp_strm_find(zram->comp);
+       locked = true;
+       user_mem = kmap_atomic(page);
+
+       if (is_partial_io(bvec)) {
+               memcpy(uncmem + offset, user_mem + bvec->bv_offset,
+                      bvec->bv_len);
+               kunmap_atomic(user_mem);
+               user_mem = NULL;
+       } else {
+               uncmem = user_mem;
+       }
+
+       if (page_zero_filled(uncmem)) {
+               if (user_mem)
+                       kunmap_atomic(user_mem);
+               /* Free memory associated with this sector now. */
+               bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+               zram_free_page(zram, index);
+               zram_set_flag(meta, index, ZRAM_ZERO);
+               bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+               atomic64_inc(&zram->stats.zero_pages);
+               ret = 0;
+               goto out;
+       }
+
+       ret = zcomp_compress(zram->comp, zstrm, uncmem, &clen);
+       if (!is_partial_io(bvec)) {
+               kunmap_atomic(user_mem);
+               user_mem = NULL;
+               uncmem = NULL;
+       }
+
+       if (unlikely(ret)) {
+               pr_err("Compression failed! err=%d\n", ret);
+               goto out;
+       }
+       src = zstrm->buffer;
+       if (unlikely(clen > max_zpage_size)) {
+               clen = PAGE_SIZE;
+               if (is_partial_io(bvec))
+                       src = uncmem;
+       }
+
+       handle = zs_malloc(meta->mem_pool, clen);
+       if (!handle) {
+               pr_info("Error allocating memory for compressed page: %u, size=%zu\n",
+                       index, clen);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       alloced_pages = zs_get_total_pages(meta->mem_pool);
+       if (zram->limit_pages && alloced_pages > zram->limit_pages) {
+               zs_free(meta->mem_pool, handle);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       update_used_max(zram, alloced_pages);
+
+       cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_WO);
+
+       if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) {
+               src = kmap_atomic(page);
+               copy_page(cmem, src);
+               kunmap_atomic(src);
+       } else {
+               memcpy(cmem, src, clen);
+       }
+
+       zcomp_strm_release(zram->comp, zstrm);
+       locked = false;
+       zs_unmap_object(meta->mem_pool, handle);
+
+       /*
+        * Free memory associated with this sector
+        * before overwriting unused sectors.
+        */
+       bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+       zram_free_page(zram, index);
+
+       meta->table[index].handle = handle;
+       zram_set_obj_size(meta, index, clen);
+       bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+
+       /* Update stats */
+       atomic64_add(clen, &zram->stats.compr_data_size);
+       atomic64_inc(&zram->stats.pages_stored);
+out:
+       if (locked)
+               zcomp_strm_release(zram->comp, zstrm);
+       if (is_partial_io(bvec))
+               kfree(uncmem);
+       return ret;
+}
+
+static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
+                       int offset, struct bio *bio)
+{
+       int ret;
+       int rw = bio_data_dir(bio);
+
+       if (rw == READ) {
+               atomic64_inc(&zram->stats.num_reads);
+               ret = zram_bvec_read(zram, bvec, index, offset, bio);
+       } else {
+               atomic64_inc(&zram->stats.num_writes);
+               ret = zram_bvec_write(zram, bvec, index, offset);
+       }
+
+       if (unlikely(ret)) {
+               if (rw == READ)
+                       atomic64_inc(&zram->stats.failed_reads);
+               else
+                       atomic64_inc(&zram->stats.failed_writes);
+       }
+
+       return ret;
+}
+
+/*
+ * zram_bio_discard - handler on discard request
+ * @index: physical block index in PAGE_SIZE units
+ * @offset: byte offset within physical block
+ */
+static void zram_bio_discard(struct zram *zram, u32 index,
+                            int offset, struct bio *bio)
+{
+       size_t n = bio->bi_size;
+       struct zram_meta *meta = zram->meta;
+
+       /*
+        * zram manages data in physical block size units. Because logical block
+        * size isn't identical with physical block size on some arch, we
+        * could get a discard request pointing to a specific offset within a
+        * certain physical block.  Although we can handle this request by
+        * reading that physiclal block and decompressing and partially zeroing
+        * and re-compressing and then re-storing it, this isn't reasonable
+        * because our intent with a discard request is to save memory.  So
+        * skipping this logical block is appropriate here.
+        */
+       if (offset) {
+               if (n <= (PAGE_SIZE - offset))
+                       return;
+
+               n -= (PAGE_SIZE - offset);
+               index++;
+       }
+
+       while (n >= PAGE_SIZE) {
+               bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+               zram_free_page(zram, index);
+               bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+               atomic64_inc(&zram->stats.notify_free);
+               index++;
+               n -= PAGE_SIZE;
+       }
+}
+
+static void zram_reset_device(struct zram *zram)
+{
+       down_write(&zram->init_lock);
+
+       zram->limit_pages = 0;
+
+       if (!init_done(zram)) {
+               up_write(&zram->init_lock);
+               return;
+       }
+
+       zcomp_destroy(zram->comp);
+       zram->max_comp_streams = 1;
+       zram_meta_free(zram->meta, zram->disksize);
+       zram->meta = NULL;
+       /* Reset stats */
+       memset(&zram->stats, 0, sizeof(zram->stats));
+
+       zram->disksize = 0;
+       up_write(&zram->init_lock);
+}
+
+static ssize_t disksize_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       u64 disksize;
+       struct zcomp *comp;
+       struct zram_meta *meta;
+       struct zram *zram = dev_to_zram(dev);
+       int err;
+
+       disksize = memparse(buf, NULL);
+       if (!disksize)
+               return -EINVAL;
+
+       disksize = PAGE_ALIGN(disksize);
+       meta = zram_meta_alloc(disksize);
+       if (!meta)
+               return -ENOMEM;
+
+       comp = zcomp_create(zram->compressor, zram->max_comp_streams);
+       if (IS_ERR(comp)) {
+               pr_info("Cannot initialise %s compressing backend\n",
+                               zram->compressor);
+               err = PTR_ERR(comp);
+               goto out_free_meta;
+       }
+
+       down_write(&zram->init_lock);
+       if (init_done(zram)) {
+               pr_info("Cannot change disksize for initialized device\n");
+               err = -EBUSY;
+               goto out_destroy_comp;
+       }
+
+       zram->meta = meta;
+       zram->comp = comp;
+       zram->disksize = disksize;
+       set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
+       up_write(&zram->init_lock);
+
+       /*
+        * Revalidate disk out of the init_lock to avoid lockdep splat.
+        * It's okay because disk's capacity is protected by init_lock
+        * so that revalidate_disk always sees up-to-date capacity.
+        */
+       revalidate_disk(zram->disk);
+
+       return len;
+
+out_destroy_comp:
+       up_write(&zram->init_lock);
+       zcomp_destroy(comp);
+out_free_meta:
+       zram_meta_free(meta, disksize);
+       return err;
+}
+
+static ssize_t reset_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       int ret;
+       unsigned short do_reset;
+       struct zram *zram;
+       struct block_device *bdev;
+
+       zram = dev_to_zram(dev);
+       bdev = bdget_disk(zram->disk, 0);
+
+       if (!bdev)
+               return -ENOMEM;
+
+       mutex_lock(&bdev->bd_mutex);
+       /* Do not reset an active device! */
+       if (bdev->bd_holders) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       ret = kstrtou16(buf, 10, &do_reset);
+       if (ret)
+               goto out;
+
+       if (!do_reset) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* Make sure all pending I/O is finished */
+       fsync_bdev(bdev);
+       zram_reset_device(zram);
+       set_capacity(zram->disk, 0);
+
+       mutex_unlock(&bdev->bd_mutex);
+       revalidate_disk(zram->disk);
+       bdput(bdev);
+
+       return len;
+
+out:
+       mutex_unlock(&bdev->bd_mutex);
+       bdput(bdev);
+       return ret;
+}
+
+static void __zram_make_request(struct zram *zram, struct bio *bio)
+{
+       int i, offset;
+       u32 index;
+       struct bio_vec *bvec;
+
+
+       index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
+       offset = (bio->bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
+
+       if (unlikely(bio->bi_rw & REQ_DISCARD)) {
+               zram_bio_discard(zram, index, offset, bio);
+               bio_endio(bio, 0);
+               return;
+       }
+
+       bio_for_each_segment(bvec, bio, i) {
+               int max_transfer_size = PAGE_SIZE - offset;
+
+               if (bvec->bv_len > max_transfer_size) {
+                       /*
+                        * zram_bvec_rw() can only make operation on a single
+                        * zram page. Split the bio vector.
+                        */
+                       struct bio_vec bv;
+
+                       bv.bv_page = bvec->bv_page;
+                       bv.bv_len = max_transfer_size;
+                       bv.bv_offset = bvec->bv_offset;
+
+                       if (zram_bvec_rw(zram, &bv, index, offset, bio) < 0)
+                               goto out;
+
+                       bv.bv_len = bvec->bv_len - max_transfer_size;
+                       bv.bv_offset += max_transfer_size;
+                       if (zram_bvec_rw(zram, &bv, index + 1, 0, bio) < 0)
+                               goto out;
+               } else
+                       if (zram_bvec_rw(zram, bvec, index, offset, bio) < 0)
+                               goto out;
+
+               update_position(&index, &offset, bvec);
+       }
+
+       set_bit(BIO_UPTODATE, &bio->bi_flags);
+       bio_endio(bio, 0);
+       return;
+
+out:
+       bio_io_error(bio);
+}
+
+/*
+ * Handler function for all zram I/O requests.
+ */
+static void zram_make_request(struct request_queue *queue, struct bio *bio)
+{
+       struct zram *zram = queue->queuedata;
+
+       down_read(&zram->init_lock);
+       if (unlikely(!init_done(zram)))
+               goto error;
+
+       if (!valid_io_request(zram, bio)) {
+               atomic64_inc(&zram->stats.invalid_io);
+               goto error;
+       }
+
+       __zram_make_request(zram, bio);
+       up_read(&zram->init_lock);
+
+       return;
+
+error:
+       up_read(&zram->init_lock);
+       bio_io_error(bio);
+}
+
+static void zram_slot_free_notify(struct block_device *bdev,
+                               unsigned long index)
+{
+       struct zram *zram;
+       struct zram_meta *meta;
+
+       zram = bdev->bd_disk->private_data;
+       meta = zram->meta;
+
+       bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
+       zram_free_page(zram, index);
+       bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
+       atomic64_inc(&zram->stats.notify_free);
+}
+
+static const struct block_device_operations zram_devops = {
+       .swap_slot_free_notify = zram_slot_free_notify,
+       .owner = THIS_MODULE
+};
+
+static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR,
+               disksize_show, disksize_store);
+static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
+static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
+static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
+static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
+static DEVICE_ATTR(mem_limit, S_IRUGO | S_IWUSR, mem_limit_show,
+               mem_limit_store);
+static DEVICE_ATTR(mem_used_max, S_IRUGO | S_IWUSR, mem_used_max_show,
+               mem_used_max_store);
+static DEVICE_ATTR(max_comp_streams, S_IRUGO | S_IWUSR,
+               max_comp_streams_show, max_comp_streams_store);
+static DEVICE_ATTR(comp_algorithm, S_IRUGO | S_IWUSR,
+               comp_algorithm_show, comp_algorithm_store);
+
+ZRAM_ATTR_RO(num_reads);
+ZRAM_ATTR_RO(num_writes);
+ZRAM_ATTR_RO(failed_reads);
+ZRAM_ATTR_RO(failed_writes);
+ZRAM_ATTR_RO(invalid_io);
+ZRAM_ATTR_RO(notify_free);
+ZRAM_ATTR_RO(zero_pages);
+ZRAM_ATTR_RO(compr_data_size);
+
+static struct attribute *zram_disk_attrs[] = {
+       &dev_attr_disksize.attr,
+       &dev_attr_initstate.attr,
+       &dev_attr_reset.attr,
+       &dev_attr_num_reads.attr,
+       &dev_attr_num_writes.attr,
+       &dev_attr_failed_reads.attr,
+       &dev_attr_failed_writes.attr,
+       &dev_attr_invalid_io.attr,
+       &dev_attr_notify_free.attr,
+       &dev_attr_zero_pages.attr,
+       &dev_attr_orig_data_size.attr,
+       &dev_attr_compr_data_size.attr,
+       &dev_attr_mem_used_total.attr,
+       &dev_attr_mem_limit.attr,
+       &dev_attr_mem_used_max.attr,
+       &dev_attr_max_comp_streams.attr,
+       &dev_attr_comp_algorithm.attr,
+       NULL,
+};
+
+static struct attribute_group zram_disk_attr_group = {
+       .attrs = zram_disk_attrs,
+};
+
+static int create_device(struct zram *zram, int device_id)
+{
+       int ret = -ENOMEM;
+
+       init_rwsem(&zram->init_lock);
+
+       zram->queue = blk_alloc_queue(GFP_KERNEL);
+       if (!zram->queue) {
+               pr_err("Error allocating disk queue for device %d\n",
+                       device_id);
+               goto out;
+       }
+
+       blk_queue_make_request(zram->queue, zram_make_request);
+       zram->queue->queuedata = zram;
+
+        /* gendisk structure */
+       zram->disk = alloc_disk(1);
+       if (!zram->disk) {
+               pr_warn("Error allocating disk structure for device %d\n",
+                       device_id);
+               goto out_free_queue;
+       }
+
+       zram->disk->major = zram_major;
+       zram->disk->first_minor = device_id;
+       zram->disk->fops = &zram_devops;
+       zram->disk->queue = zram->queue;
+       zram->disk->private_data = zram;
+       snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
+
+       /* Actual capacity set using syfs (/sys/block/zram<id>/disksize */
+       set_capacity(zram->disk, 0);
+       /* zram devices sort of resembles non-rotational disks */
+       queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
+       /*
+        * To ensure that we always get PAGE_SIZE aligned
+        * and n*PAGE_SIZED sized I/O requests.
+        */
+       blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE);
+       blk_queue_logical_block_size(zram->disk->queue,
+                                       ZRAM_LOGICAL_BLOCK_SIZE);
+       blk_queue_io_min(zram->disk->queue, PAGE_SIZE);
+       blk_queue_io_opt(zram->disk->queue, PAGE_SIZE);
+       zram->disk->queue->limits.discard_granularity = PAGE_SIZE;
+       zram->disk->queue->limits.max_discard_sectors = UINT_MAX;
+       /*
+        * zram_bio_discard() will clear all logical blocks if logical block
+        * size is identical with physical block size(PAGE_SIZE). But if it is
+        * different, we will skip discarding some parts of logical blocks in
+        * the part of the request range which isn't aligned to physical block
+        * size.  So we can't ensure that all discarded logical blocks are
+        * zeroed.
+        */
+       if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE)
+               zram->disk->queue->limits.discard_zeroes_data = 1;
+       else
+               zram->disk->queue->limits.discard_zeroes_data = 0;
+       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, zram->disk->queue);
+
+       add_disk(zram->disk);
+
+       ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
+                               &zram_disk_attr_group);
+       if (ret < 0) {
+               pr_warn("Error creating sysfs group");
+               goto out_free_disk;
+       }
+       strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
+       zram->meta = NULL;
+       zram->max_comp_streams = 1;
+       return 0;
+
+out_free_disk:
+       del_gendisk(zram->disk);
+       put_disk(zram->disk);
+out_free_queue:
+       blk_cleanup_queue(zram->queue);
+out:
+       return ret;
+}
+
+static void destroy_device(struct zram *zram)
+{
+       sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
+                       &zram_disk_attr_group);
+
+       del_gendisk(zram->disk);
+       put_disk(zram->disk);
+
+       blk_cleanup_queue(zram->queue);
+}
+
+static int __init zram_init(void)
+{
+       int ret, dev_id;
+
+       if (num_devices > max_num_devices) {
+               pr_warn("Invalid value for num_devices: %u\n",
+                               num_devices);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       zram_major = register_blkdev(0, "zram");
+       if (zram_major <= 0) {
+               pr_warn("Unable to get major number\n");
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* Allocate the device array and initialize each one */
+       zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
+       if (!zram_devices) {
+               ret = -ENOMEM;
+               goto unregister;
+       }
+
+       for (dev_id = 0; dev_id < num_devices; dev_id++) {
+               ret = create_device(&zram_devices[dev_id], dev_id);
+               if (ret)
+                       goto free_devices;
+       }
+
+       pr_info("Created %u device(s) ...\n", num_devices);
+
+       return 0;
+
+free_devices:
+       while (dev_id)
+               destroy_device(&zram_devices[--dev_id]);
+       kfree(zram_devices);
+unregister:
+       unregister_blkdev(zram_major, "zram");
+out:
+       return ret;
+}
+
+static void __exit zram_exit(void)
+{
+       int i;
+       struct zram *zram;
+
+       for (i = 0; i < num_devices; i++) {
+               zram = &zram_devices[i];
+
+               destroy_device(zram);
+               /*
+                * Shouldn't access zram->disk after destroy_device
+                * because destroy_device already released zram->disk.
+                */
+               zram_reset_device(zram);
+       }
+
+       unregister_blkdev(zram_major, "zram");
+
+       kfree(zram_devices);
+       pr_debug("Cleanup done!\n");
+}
+
+module_init(zram_init);
+module_exit(zram_exit);
+
+module_param(num_devices, uint, 0);
+MODULE_PARM_DESC(num_devices, "Number of zram devices");
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
+MODULE_DESCRIPTION("Compressed RAM Block Device");
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
new file mode 100644 (file)
index 0000000..b05a816
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Compressed RAM block device
+ *
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
+ *               2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+#ifndef _ZRAM_DRV_H_
+#define _ZRAM_DRV_H_
+
+#include <linux/spinlock.h>
+#include <linux/zsmalloc.h>
+
+#include "zcomp.h"
+
+/*
+ * Some arbitrary value. This is just to catch
+ * invalid value for num_devices module parameter.
+ */
+static const unsigned max_num_devices = 32;
+
+/*-- Configurable parameters */
+
+/*
+ * Pages that compress to size greater than this are stored
+ * uncompressed in memory.
+ */
+static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
+
+/*
+ * NOTE: max_zpage_size must be less than or equal to:
+ *   ZS_MAX_ALLOC_SIZE. Otherwise, zs_malloc() would
+ * always return failure.
+ */
+
+/*-- End of configurable params */
+
+#define SECTOR_SHIFT           9
+#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
+#define SECTORS_PER_PAGE       (1 << SECTORS_PER_PAGE_SHIFT)
+#define ZRAM_LOGICAL_BLOCK_SHIFT 12
+#define ZRAM_LOGICAL_BLOCK_SIZE        (1 << ZRAM_LOGICAL_BLOCK_SHIFT)
+#define ZRAM_SECTOR_PER_LOGICAL_BLOCK  \
+       (1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
+
+
+/*
+ * The lower ZRAM_FLAG_SHIFT bits of table.value is for
+ * object size (excluding header), the higher bits is for
+ * zram_pageflags.
+ *
+ * zram is mainly used for memory efficiency so we want to keep memory
+ * footprint small so we can squeeze size and flags into a field.
+ * The lower ZRAM_FLAG_SHIFT bits is for object size (excluding header),
+ * the higher bits is for zram_pageflags.
+ */
+#define ZRAM_FLAG_SHIFT 24
+
+/* Flags for zram pages (table[page_no].value) */
+enum zram_pageflags {
+       /* Page consists entirely of zeros */
+       ZRAM_ZERO = ZRAM_FLAG_SHIFT,
+       ZRAM_ACCESS,    /* page is now accessed */
+
+       __NR_ZRAM_PAGEFLAGS,
+};
+
+/*-- Data structures */
+
+/* Allocated for each disk page */
+struct zram_table_entry {
+       unsigned long handle;
+       unsigned long value;
+};
+
+struct zram_stats {
+       atomic64_t compr_data_size;     /* compressed size of pages stored */
+       atomic64_t num_reads;   /* failed + successful */
+       atomic64_t num_writes;  /* --do-- */
+       atomic64_t failed_reads;        /* can happen when memory is too low */
+       atomic64_t failed_writes;       /* can happen when memory is too low */
+       atomic64_t invalid_io;  /* non-page-aligned I/O requests */
+       atomic64_t notify_free; /* no. of swap slot free notifications */
+       atomic64_t zero_pages;          /* no. of zero filled pages */
+       atomic64_t pages_stored;        /* no. of pages currently stored */
+       atomic_long_t max_used_pages;   /* no. of maximum pages stored */
+};
+
+struct zram_meta {
+       struct zram_table_entry *table;
+       struct zs_pool *mem_pool;
+};
+
+struct zram {
+       struct zram_meta *meta;
+       struct request_queue *queue;
+       struct gendisk *disk;
+       struct zcomp *comp;
+
+       /* Prevent concurrent execution of device init, reset and R/W request */
+       struct rw_semaphore init_lock;
+       /*
+        * This is the limit on amount of *uncompressed* worth of data
+        * we can store in a disk.
+        */
+       u64 disksize;   /* bytes */
+       int max_comp_streams;
+       struct zram_stats stats;
+       /*
+        * the number of pages zram can consume for storing compressed data
+        */
+       unsigned long limit_pages;
+
+       char compressor[10];
+};
+#endif
index dad8891ecbfa1b202fd65ec5d42231196c826ee3..9c2c4eca52e30572d385dd9468e17b907c511f0d 100644 (file)
@@ -77,6 +77,8 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x0CF3, 0x3004) },
        { USB_DEVICE(0x0CF3, 0x3008) },
        { USB_DEVICE(0x0CF3, 0x311D) },
+       { USB_DEVICE(0x0CF3, 0x311E) },
+       { USB_DEVICE(0x0CF3, 0x311F) },
        { USB_DEVICE(0x0CF3, 0x817a) },
        { USB_DEVICE(0x13d3, 0x3375) },
        { USB_DEVICE(0x04CA, 0x3004) },
@@ -120,6 +122,8 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
index 61a8ec4e5f4d7045bd280a86b2989fc0db9b11bc..92b985317770e38ab4d0e1e1a17f95faf74ee380 100644 (file)
@@ -49,6 +49,7 @@ static struct usb_driver btusb_driver;
 #define BTUSB_WRONG_SCO_MTU    0x40
 #define BTUSB_ATH3012          0x80
 #define BTUSB_INTEL            0x100
+#define BTUSB_INTEL_BOOT       0x200
 
 static struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth USB device */
@@ -113,6 +114,13 @@ static struct usb_device_id btusb_table[] = {
        /*Broadcom devices with vendor specific id */
        { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
 
+       /* IMC Networks - Broadcom based */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
+
+       /* Intel Bluetooth USB Bootloader (RAM module) */
+       { USB_DEVICE(0x8087, 0x0a5a),
+         .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
+
        { }     /* Terminating entry */
 };
 
@@ -141,6 +149,8 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
@@ -1444,6 +1454,9 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_INTEL)
                hdev->setup = btusb_setup_intel;
 
+       if (id->driver_info & BTUSB_INTEL_BOOT)
+               set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
+
        /* Interface numbers are hardcoded in the specification */
        data->isoc = usb_ifnum_to_if(data->udev, 1);
 
index 3b4d68546f5650fd9c1002dcdca1483985e374c9..23faa5e3671348dfafd1fdba8b875c3b6c31865e 100644 (file)
@@ -375,7 +375,7 @@ static void cpufreq_interactive_timer(unsigned long data)
        spin_lock_irqsave(&pcpu->target_freq_lock, flags);
        do_div(cputime_speedadj, delta_time);
        loadadjfreq = (unsigned int)cputime_speedadj * 100;
-       cpu_load = loadadjfreq / pcpu->target_freq;
+       cpu_load = loadadjfreq / pcpu->policy->cur;
        tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime;
 
 #ifdef CONFIG_ARCH_ROCKCHIP
index ec3fc4fd9160e8aeddf16054cd405f35b43bfef7..b94a37630e368f8953a257b290836a1680fb6785 100644 (file)
@@ -487,6 +487,7 @@ static int omap_dma_terminate_all(struct omap_chan *c)
         * c->desc is NULL and exit.)
         */
        if (c->desc) {
+               omap_dma_desc_free(&c->desc->vd);
                c->desc = NULL;
                /* Avoid stopping the dma twice */
                if (!c->paused)
index e04462b6075679c6106e13a645ea061fceca4ba5..f505e4ca6d58efe28410f82db03cd378c5eb930e 100644 (file)
@@ -270,8 +270,9 @@ static const u32 correrrthrsld[] = {
  * sbridge structs
  */
 
-#define NUM_CHANNELS   4
-#define MAX_DIMMS      3               /* Max DIMMS per channel */
+#define NUM_CHANNELS           4
+#define MAX_DIMMS              3       /* Max DIMMS per channel */
+#define CHANNEL_UNSPECIFIED    0xf     /* Intel IA32 SDM 15-14 */
 
 struct sbridge_info {
        u32     mcmtr;
@@ -1451,6 +1452,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
 
        /* FIXME: need support for channel mask */
 
+       if (channel == CHANNEL_UNSPECIFIED)
+               channel = -1;
+
        /* Call the helper to output message */
        edac_mc_handle_error(tp_event, mci, core_err_cnt,
                             m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
diff --git a/drivers/gator/COPYING b/drivers/gator/COPYING
new file mode 100644 (file)
index 0000000..d159169
--- /dev/null
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/drivers/gator/LICENSE b/drivers/gator/LICENSE
deleted file mode 100644 (file)
index d159169..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                            NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
index 28d2070b11d54304605612c05b1dd198f3afc783..d14e2a02fee0d25eb65b6d36397b12886ec8b34d 100644 (file)
@@ -63,6 +63,22 @@ gator-$(CONFIG_ARM) +=       gator_events_armv6.o \
 
 gator-$(CONFIG_ARM64) +=
 
+$(obj)/gator_main.o: $(obj)/gator_src_md5.h
+
+clean-files := gator_src_md5.h
+
+# Note, in the recipe below we use "cd $(srctree) && cd $(src)" rather than
+# "cd $(srctree)/$(src)" because under DKMS $(src) is an absolute path, and we
+# can't just use $(src) because for normal kernel builds this is relative to
+# $(srctree)
+
+       chk_events.h = :
+ quiet_chk_events.h = echo '  CHK     $@'
+silent_chk_events.h = :
+$(obj)/gator_src_md5.h: FORCE
+       @$($(quiet)chk_events.h)
+       $(Q)cd $(srctree) && cd $(src) ; $(CONFIG_SHELL) -c "echo 'static char *gator_src_md5 = \"'\`ls *.c *.h mali/*.h | grep -Ev '^(gator_src_md5\.c|gator\.mod\.c)$$' | LC_ALL=C sort | xargs cat | md5sum | cut -b 1-32\`'\";'" > $(abspath $@)
+
 else
 
 all:
@@ -73,7 +89,7 @@ all:
        $(error)
 
 clean:
-       rm -f *.o .*.cmd modules.order Module.symvers gator.ko gator.mod.c
+       rm -f *.o .*.cmd gator_src_md5.h modules.order Module.symvers gator.ko gator.mod.c
        rm -rf .tmp_versions
 
 endif
index 5cc73a388c4f71a13fd5baecf4a42e68c36f3922..202eb41c485b03c5d348c2cfe21de0ab00238311 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
 #define GATOR_IKS_SUPPORT       defined(CONFIG_BL_SWITCHER)
 
 /* cpu ids */
-#define ARM1136     0xb36
-#define ARM1156     0xb56
-#define ARM1176     0xb76
-#define ARM11MPCORE 0xb02
-#define CORTEX_A5   0xc05
-#define CORTEX_A7   0xc07
-#define CORTEX_A8   0xc08
-#define CORTEX_A9   0xc09
-#define CORTEX_A15  0xc0f
-#define CORTEX_A17  0xc0e
-#define SCORPION    0x00f
-#define SCORPIONMP  0x02d
-#define KRAITSIM    0x049
-#define KRAIT       0x04d
-#define KRAIT_S4_PRO 0x06f
-#define CORTEX_A53  0xd03
-#define CORTEX_A57  0xd07
-#define AARCH64     0xd0f
-#define OTHER       0xfff
+#define ARM1136      0x41b36
+#define ARM1156      0x41b56
+#define ARM1176      0x41b76
+#define ARM11MPCORE  0x41b02
+#define CORTEX_A5    0x41c05
+#define CORTEX_A7    0x41c07
+#define CORTEX_A8    0x41c08
+#define CORTEX_A9    0x41c09
+#define CORTEX_A15   0x41c0f
+#define CORTEX_A12   0x41c0d
+#define CORTEX_A17   0x41c0e
+#define SCORPION     0x5100f
+#define SCORPIONMP   0x5102d
+#define KRAITSIM     0x51049
+#define KRAIT        0x5104d
+#define KRAIT_S4_PRO 0x5106f
+#define CORTEX_A53   0x41d03
+#define CORTEX_A57   0x41d07
+#define CORTEX_A72   0x41d08
+#define OTHER        0xfffff
 
 /* gpu enums */
 #define MALI_4xx     1
index ff9a3cef7b2e3b8b3bc51d7dc4d5d632e46cf70f..cc9ae02e5fba58872beb67ee85a4aa486a7a45ad 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 69471f99e5fb3769957dc2d341a4792cf89c1302..54e8e86e34cf32626e668aa479b2308187afe68c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2012-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2012-2015. All rights reserved.
  *
  * 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
index 76c941d009a9afdcaf15fa682b3bd40004b39166..5557ec0b29ca3c00c20d2674768e7ec99db2e238 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 910d5aa1506697d0c22dc0120547b92e6f24a0bd..f335457638aeccfad23a25a0e9e68cee8b02cbaa 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 654ec606cfad66d1dd776bd5c44039a856e36f20..b731e6a414d21f67af27c60bbc3c016d43c2ce77 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index c43cce81522649c00e61bfbde8bde4da178cfd0e..9bd4c8b98c9e763b850a85b268156d0a9d624454 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index a157a0013302e8e5aaaf998c074352135a22be4c..178397033e2cabe3becd362e8659d7fd26f95664 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 09c94220114ca018f0a42986ba24dce7e579b255..e1f6a5fa999719865faf4f951f4d0e0cc741bd65 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index a352a54afa025d5ab4927fd3936f9807fb815b8e..b3467b1337120ec6612aa73c5615c42aab27ff0d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 5221aac581b3327aa34fda11f5e2c3bd7b879aed..81b976a9b282c78591204e395fc41abc198cb613 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 73aaac32327e8ea1582557e6839f718c8da5d94c..063a06079c743a884cf24d6c449d1c2d1762ad84 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * l2c310 (L2 Cache Controller) event counters for gator
  *
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 9cf43fe2c29b3565d93096a58cf8ad73b3c2eccd..423b4e08e8ccaa5c9d8deb1197e6a942b18a7e3a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 976ca8c4cfa1af78567327951a2ab1de2b094f04..8f6a870e6d0cf51b4a3fc4767dc1854d08d34433 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2011-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2011-2015. All rights reserved.
  *
  * 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
index 1af87d649afe0f763b5f617ba88c5bc04cdcd16f..7741f257554260087ea7e70a7742560fbb184727 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2012-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2012-2015. All rights reserved.
  *
  * 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
index e7082e62fe88c3b0250b5a52dbcc283bcbb84c63..a4fc9d7d4cf68d3ca374a2fa0e28e5376965c770 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2012-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2012-2015. All rights reserved.
  *
  * 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
index 0aec906d7ae5c2f0bf097f4b125bd4fa4b7709db..3b0963a8de21f2c80ac4ce007f5cabe1dadb4667 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2011-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2011-2015. All rights reserved.
  *
  * 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
index c8065da56815f01c4ac163be5a60dd93221611a2..7e1eee30026d101b2fd230ae4c0c95f5afe9b914 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2012-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2012-2015. All rights reserved.
  *
  * 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
@@ -18,7 +18,7 @@
 /* Mali Midgard DDK includes */
 #if defined(MALI_SIMPLE_API)
 /* Header with wrapper functions to kbase structures and functions */
-#include "mali/mali_kbase_gator_api.h"
+#include "mali_kbase_gator_api.h"
 #elif defined(MALI_DIR_MIDGARD)
 /* New DDK Directory structure with kernel/drivers/gpu/arm/midgard */
 #include "mali_linux_trace.h"
 #error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3/r4 DDK, or 3 for r5 and later DDK).
 #endif
 
+#if !defined(CONFIG_MALI_GATOR_SUPPORT)
+#error CONFIG_MALI_GATOR_SUPPORT is required for GPU activity and software counters
+#endif
+
 #include "gator_events_mali_common.h"
 
 /*
@@ -748,12 +752,12 @@ static int read_counter(const int cnt, const int len, const struct mali_counter
 {
        const int block = GET_HW_BLOCK(cnt);
        const int counter_offset = GET_COUNTER_OFFSET(cnt);
+       u32 value = 0;
 
 #if MALI_DDK_GATOR_API_VERSION == 3
        const char *block_base_address = (char *)in_out_info->kernel_dump_buffer;
        int i;
        int shader_core_count = 0;
-       u32 value = 0;
 
        for (i = 0; i < in_out_info->nr_hwc_blocks; i++) {
                if (block == in_out_info->hwc_layout[i]) {
@@ -766,6 +770,12 @@ static int read_counter(const int cnt, const int len, const struct mali_counter
        if (shader_core_count > 1)
                value /= shader_core_count;
 #else
+       const unsigned int vithar_blocks[] = {
+               0x700,  /* VITHAR_JOB_MANAGER,     Block 0 */
+               0x400,  /* VITHAR_TILER,           Block 1 */
+               0x000,  /* VITHAR_SHADER_CORE,     Block 2 */
+               0x500   /* VITHAR_MEMORY_SYSTEM,   Block 3 */
+       };
        const char *block_base_address = (char *)kernel_dump_buffer + vithar_blocks[block];
 
        /* If counter belongs to shader block need to take into account all cores */
@@ -831,31 +841,22 @@ static int read(int **buffer, bool sched_switch)
         * Only process hardware counters if at least one of the hardware counters is enabled.
         */
        if (num_hardware_counters_enabled > 0) {
-#if MALI_DDK_GATOR_API_VERSION != 3
-               const unsigned int vithar_blocks[] = {
-                       0x700,  /* VITHAR_JOB_MANAGER,     Block 0 */
-                       0x400,  /* VITHAR_TILER,           Block 1 */
-                       0x000,  /* VITHAR_SHADER_CORE,     Block 2 */
-                       0x500   /* VITHAR_MEMORY_SYSTEM,   Block 3 */
-               };
-#endif
-
 #if MALI_DDK_GATOR_API_VERSION == 3
                if (!handles)
                        return -1;
 
                /* Mali symbols can be called safely since a kbcontext is valid */
-               if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) {
+               if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success)) {
 #else
                if (!kbcontext)
                        return -1;
 
                /* Mali symbols can be called safely since a kbcontext is valid */
-               if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) {
+               if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success)) {
 #endif
                        kbase_device_busy = false;
 
-                       if (success == MALI_TRUE) {
+                       if (success) {
                                /* Cycle through hardware counters and accumulate totals */
                                for (cnt = 0; cnt < number_of_hardware_counters; cnt++) {
                                        const struct mali_counter *counter = &counters[cnt];
index 31a91e1c72b28c788e08c70ffb29a56782e8ee09..87c569cabf536ae1bb5388bb051c041a4359223d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2012-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2012-2015. All rights reserved.
  *
  * 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
index c625ac5af9cd37fac1951535ba4092f08e6b0e59..985b312ab92bc80a23522172ecbc673fb08f0e26 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -58,6 +58,8 @@ static ulong proc_enabled[PROC_COUNT];
 static ulong proc_keys[PROC_COUNT];
 static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]);
 
+static void do_read(void);
+
 #if USE_THREAD
 
 static int gator_meminfo_func(void *data);
@@ -177,6 +179,7 @@ static int gator_events_meminfo_start(void)
        if (GATOR_REGISTER_TRACE(mm_page_alloc))
                goto mm_page_alloc_exit;
 
+       do_read();
 #if USE_THREAD
        /* Start worker thread */
        gator_meminfo_run = true;
index 6b2af995ed41e7623ca06473e1e0724819496e5c..7b517611f8ec2580d4718be7225ecf8e9176829f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Example events provider
  *
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index d21b4db7b77cde5455ac91da54548651358d2947..1e36731479d20417f7504d71af0d1f27f30278a3 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 47cf278e508b110fa7746fb2bf8d9a7d2420eeb5..f6b4f18ad11a8c21ffb9ff217099d4a614ebedb3 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -23,11 +23,13 @@ extern bool event_based_sampling;
 /* Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE */
 #define CNTMAX 16
 #define CCI_400 4
+#define CCI_500 8
 #define CCN_5XX 8
 /* Maximum number of uncore counters */
 /* + 1 for the cci-400 cycles counter */
+/* cci-500 has no cycles counter */
 /* + 1 for the CCN-5xx cycles counter */
-#define UCCNT (CCI_400 + 1 + CCN_5XX + 1)
+#define UCCNT (CCI_400 + 1 + CCI_500 + CCN_5XX + 1)
 
 /* Default to 0 if unable to probe the revision which was the previous behavior */
 #define DEFAULT_CCI_REVISION 0
@@ -58,9 +60,9 @@ static struct gator_attr uc_attrs[UCCNT];
 static int uc_attr_count;
 
 struct gator_event {
-       int curr;
-       int prev;
-       int prev_delta;
+       uint32_t curr;
+       uint32_t prev;
+       uint32_t prev_delta;
        bool zero;
        struct perf_event *pevent;
        struct perf_event_attr *pevent_attr;
@@ -315,7 +317,7 @@ static void gator_events_perf_pmu_stop(void)
 
 static void __read(int *const len, int cpu, struct gator_attr *const attr, struct gator_event *const event)
 {
-       int delta;
+       uint32_t delta;
        struct perf_event *const ev = event->pevent;
 
        if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) {
@@ -341,8 +343,6 @@ static void __read(int *const len, int cpu, struct gator_attr *const attr, struc
                                event->prev_delta = delta;
                                event->prev = event->curr;
                                per_cpu(perf_cnt, cpu)[(*len)++] = attr->key;
-                               if (delta < 0)
-                                       delta *= -1;
                                per_cpu(perf_cnt, cpu)[(*len)++] = delta;
                        }
                }
@@ -436,13 +436,15 @@ static int probe_cci_revision(void)
 
 #endif
 
-static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count)
+static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count, const bool has_cycles_counter)
 {
        int cnt;
 
-       snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name);
-       uc_attrs[uc_attr_count].type = type;
-       ++uc_attr_count;
+       if (has_cycles_counter) {
+               snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name);
+               uc_attrs[uc_attr_count].type = type;
+               ++uc_attr_count;
+       }
 
        for (cnt = 0; cnt < count; ++cnt, ++uc_attr_count) {
                struct gator_attr *const attr = &uc_attrs[uc_attr_count];
@@ -452,7 +454,7 @@ static void gator_events_perf_pmu_uncore_init(const char *const name, const int
        }
 }
 
-static void gator_events_perf_pmu_cci_init(const int type)
+static void gator_events_perf_pmu_cci_400_init(const int type)
 {
        const char *cci_name;
 
@@ -468,7 +470,7 @@ static void gator_events_perf_pmu_cci_init(const int type)
                return;
        }
 
-       gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400);
+       gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400, true);
 }
 
 static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_cpu, const int type)
@@ -535,9 +537,11 @@ int gator_events_perf_pmu_init(void)
 
                if (pe->pmu != NULL && type == pe->pmu->type) {
                        if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) {
-                               gator_events_perf_pmu_cci_init(type);
+                               gator_events_perf_pmu_cci_400_init(type);
+                       } else if (strcmp("CCI_500", pe->pmu->name) == 0) {
+                               gator_events_perf_pmu_uncore_init("CCI_500", type, CCI_500, false);
                        } else if (strcmp("ccn", pe->pmu->name) == 0) {
-                               gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX);
+                               gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX, true);
                        } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) {
                                found_cpu = true;
                                gator_events_perf_pmu_cpu_init(gator_cpu, type);
@@ -549,10 +553,15 @@ int gator_events_perf_pmu_init(void)
        }
 
        if (!found_cpu) {
-               const struct gator_cpu *const gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid());
+               const struct gator_cpu *gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid());
 
-               if (gator_cpu == NULL)
-                       return -1;
+               if (gator_cpu == NULL) {
+                       gator_cpu = gator_find_cpu_by_cpuid(OTHER);
+                       if (gator_cpu == NULL) {
+                               pr_err("gator: Didn't find cpu\n");
+                               return -1;
+                       }
+               }
                gator_events_perf_pmu_cpu_init(gator_cpu, PERF_TYPE_RAW);
        }
 
index 637107d6af1d6c8b4c8048d0f352380d17ee0d3f..463d834960736642faca325023bf4669e034b7ba 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 49219362db092515ee590c002dbc66cff870d977..b51dcd39a8e10fb9d175a4cbcdcb5b37daf03fe0 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2011-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2011-2015. All rights reserved.
  *
  * 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
index c1525e10a8da37cd67c91a5a41ab947c78d6e612..36961f85b62a0995836c5f5e2b3a84f4173e741d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2011-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2011-2015. All rights reserved.
  *
  * 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
index fb78c10fd987458f7bcdb99cacc55b3e3ab0e22c..80535c7b2b6eb2cb70b8cc3aafdf952bff7a1fdc 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 30bf60d952869d83280c16c0bb6390405954b3d1..affa1dc312e4462e886dcadf7bb4c44b2bb3b9bb 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -8,7 +8,7 @@
  */
 
 /* This version must match the gator daemon version */
-#define PROTOCOL_VERSION 20
+#define PROTOCOL_VERSION 21
 static unsigned long gator_protocol_version = PROTOCOL_VERSION;
 
 #include <linux/slab.h>
@@ -28,6 +28,7 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
 #include <linux/uaccess.h>
 
 #include "gator.h"
+#include "gator_src_md5.h"
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
 #error kernels prior to 2.6.32 are not supported
@@ -92,21 +93,17 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION;
 /* Name Frame Messages */
 #define MESSAGE_COOKIE      1
 #define MESSAGE_THREAD_NAME 2
-#define MESSAGE_LINK        4
 
 /* Scheduler Trace Frame Messages */
 #define MESSAGE_SCHED_SWITCH 1
 #define MESSAGE_SCHED_EXIT   2
 
-/* Idle Frame Messages */
-#define MESSAGE_IDLE_ENTER 1
-#define MESSAGE_IDLE_EXIT  2
-
 /* Summary Frame Messages */
 #define MESSAGE_SUMMARY   1
 #define MESSAGE_CORE_NAME 3
 
 /* Activity Frame Messages */
+#define MESSAGE_LINK   1
 #define MESSAGE_SWITCH 2
 #define MESSAGE_EXIT   3
 
@@ -267,6 +264,9 @@ GATOR_EVENTS_LIST
  * Misc
  ******************************************************************************/
 
+MODULE_PARM_DESC(gator_src_md5, "Gator driver source code md5sum");
+module_param_named(src_md5, gator_src_md5, charp, 0444);
+
 static const struct gator_cpu gator_cpus[] = {
        {
                .cpuid = ARM1136,
@@ -331,6 +331,13 @@ static const struct gator_cpu gator_cpus[] = {
                .dt_name = "arm,cortex-a15",
                .pmnc_counters = 6,
        },
+       {
+               .cpuid = CORTEX_A12,
+               .core_name = "Cortex-A17",
+               .pmnc_name = "ARMv7_Cortex_A17",
+               .dt_name = "arm,cortex-a17",
+               .pmnc_counters = 6,
+       },
        {
                .cpuid = CORTEX_A17,
                .core_name = "Cortex-A17",
@@ -383,9 +390,10 @@ static const struct gator_cpu gator_cpus[] = {
                .pmnc_counters = 6,
        },
        {
-               .cpuid = AARCH64,
-               .core_name = "AArch64",
-               .pmnc_name = "ARM_AArch64",
+               .cpuid = CORTEX_A72,
+               .core_name = "Cortex-A72",
+               .pmnc_name = "ARM_Cortex-A72",
+               .dt_name = "arm,cortex-a72",
                .pmnc_counters = 6,
        },
        {
@@ -443,7 +451,7 @@ u32 gator_cpuid(void)
 #else
        asm volatile("mrs %0, midr_el1" : "=r" (val));
 #endif
-       return (val >> 4) & 0xfff;
+       return ((val & 0xff000000) >> 12) | ((val & 0xfff0) >> 4);
 #else
        return OTHER;
 #endif
@@ -597,7 +605,7 @@ static void gator_send_core_name(const int cpu, const u32 cpuid)
                        if (cpuid == -1)
                                snprintf(core_name_buf, sizeof(core_name_buf), "Unknown");
                        else
-                               snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid);
+                               snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.5x)", cpuid);
                        core_name = core_name_buf;
                }
 
@@ -729,11 +737,11 @@ static void gator_emit_perf_time(u64 time)
 {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
        if (time >= gator_sync_time) {
-               int cpu = get_physical_cpu();
-
                marshal_event_single64(0, -1, local_clock());
                gator_sync_time += NSEC_PER_SEC;
-               gator_commit_buffer(cpu, COUNTER_BUF, time);
+               if (gator_live_rate <= 0) {
+                       gator_commit_buffer(get_physical_cpu(), COUNTER_BUF, time);
+               }
        }
 #endif
 }
@@ -867,7 +875,9 @@ static void gator_summary(void)
 
        marshal_summary(timestamp, uptime, gator_monotonic_started, uname_buf);
        gator_sync_time = 0;
-       gator_emit_perf_time(gator_monotonic_started);  
+       gator_emit_perf_time(gator_monotonic_started);
+       /* Always flush COUNTER_BUF so that the initial perf_time is received before it's used */
+       gator_commit_buffer(get_physical_cpu(), COUNTER_BUF, 0);
        preempt_enable();
 }
 
index 0d11676436429640d91b41fec7f0ce79c5a40321..f5b81843d1c4902aa4325bd9bac135a19a49e74a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2012-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2012-2015. All rights reserved.
  *
  * 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
@@ -107,16 +107,16 @@ static void marshal_link(int cookie, int tgid, int pid)
 
        local_irq_save(flags);
        time = gator_get_time();
-       if (buffer_check_space(cpu, NAME_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
-               gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_LINK);
-               gator_buffer_write_packed_int64(cpu, NAME_BUF, time);
-               gator_buffer_write_packed_int(cpu, NAME_BUF, cookie);
-               gator_buffer_write_packed_int(cpu, NAME_BUF, tgid);
-               gator_buffer_write_packed_int(cpu, NAME_BUF, pid);
+       if (buffer_check_space(cpu, ACTIVITY_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32)) {
+               gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, MESSAGE_LINK);
+               gator_buffer_write_packed_int64(cpu, ACTIVITY_BUF, time);
+               gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, cookie);
+               gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, tgid);
+               gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, pid);
        }
        local_irq_restore(flags);
        /* Check and commit; commit is set to occur once buffer is 3/4 full */
-       buffer_check(cpu, NAME_BUF, time);
+       buffer_check(cpu, ACTIVITY_BUF, time);
 }
 
 static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 time)
index 5de9152e365aa4cdf4229c515fa9144df1efe07c..d9b82ee1857f1900019925e2715a360c4355d5e1 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 46e04b29a18748c3058819850fbd6664d4329f7c..aaa8f8636c835d6704ea260d2fcec6495eae00e4 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2011-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2011-2015. All rights reserved.
  *
  * 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
@@ -80,13 +80,7 @@ GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu))
                return;
 
        if (implements_wfi()) {
-               if (state == PWR_EVENT_EXIT) {
-                       /* transition from wfi to non-wfi */
-                       marshal_idle(cpu, MESSAGE_IDLE_EXIT);
-               } else {
-                       /* transition from non-wfi to wfi */
-                       marshal_idle(cpu, MESSAGE_IDLE_ENTER);
-               }
+               marshal_idle(cpu, state);
        }
 
        per_cpu(idle_prev_state, cpu) = state;
index 6d7cbd7348e151d43fe992b521caf89311fe5be6..ad7c39e14a171e7746583547573ec9e353d2e5fd 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
diff --git a/drivers/gator/mali/mali_kbase_gator_api.h b/drivers/gator/mali/mali_kbase_gator_api.h
deleted file mode 100644 (file)
index 5ed0697..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#ifndef _KBASE_GATOR_API_H_
-#define _KBASE_GATOR_API_H_
-
-/**
- * @brief This file describes the API used by Gator to collect hardware counters data from a Mali device.
- */
-
-/* This define is used by the gator kernel module compile to select which DDK
- * API calling convention to use. If not defined (legacy DDK) gator assumes
- * version 1. The version to DDK release mapping is:
- *     Version 1 API: DDK versions r1px, r2px
- *     Version 2 API: DDK versions r3px, r4px
- *     Version 3 API: DDK version r5p0 and newer
- *
- * API Usage
- * =========
- *
- * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter
- * names for the GPU present in this device.
- *
- * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for
- * the counters you want enabled. The enables can all be set for simplicity in
- * most use cases, but disabling some will let you minimize bandwidth impact.
- *
- * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a
- * counter context. On successful return the DDK will have populated the
- * structure with a variety of useful information.
- *
- * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a
- * counter dump. If this returns a non-zero value the request has been queued,
- * otherwise the driver has been unable to do so (typically because of another
- * user of the instrumentation exists concurrently).
- *
- * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the  previously
- * requested dump has been succesful. If this returns non-zero the counter dump
- * has resolved, but the value of *success must also be tested as the dump
- * may have not been successful. If it returns zero the counter dump was
- * abandoned due to the device being busy (typically because of another
- * user of the instrumentation exists concurrently).
- *
- * 6] Process the counters stored in the buffer pointed to by ...
- *
- *        kbase_gator_hwcnt_info->kernel_dump_buffer
- *
- *    In pseudo code you can find all of the counters via this approach:
- *
- *
- *        hwcnt_info # pointer to kbase_gator_hwcnt_info structure
- *        hwcnt_name # pointer to name list
- *
- *        u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer
- *
- *        # Iterate over each 64-counter block in this GPU configuration
- *        for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) {
- *            hwc_type type = hwcnt_info->hwc_layout[i];
- *
- *            # Skip reserved type blocks - they contain no counters at all
- *            if( type == RESERVED_BLOCK ) {
- *                continue;
- *            }
- *
- *            size_t name_offset = type * 64;
- *            size_t data_offset = i * 64;
- *
- *            # Iterate over the names of the counters in this block type
- *            for( j = 0; j < 64; j++) {
- *                const char * name = hwcnt_name[name_offset+j];
- *
- *                # Skip empty name strings - there is no counter here
- *                if( name[0] == '\0' ) {
- *                    continue;
- *                }
- *
- *                u32 data = hwcnt_data[data_offset+j];
- *
- *                printk( "COUNTER: %s DATA: %u\n", name, data );
- *            }
- *        }
- *
- *
- *     Note that in most implementations you typically want to either SUM or
- *     AVERAGE multiple instances of the same counter if, for example, you have
- *     multiple shader cores or multiple L2 caches. The most sensible view for
- *     analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU
- *     counters.
- *
- * 7] Goto 4, repeating until you want to stop collecting counters.
- *
- * 8] Release the dump resources by calling kbase_gator_hwcnt_term().
- *
- * 9] Release the name table resources by calling kbase_gator_hwcnt_term_names().
- *    This function must only be called if init_names() returned a non-NULL value.
- **/
-
-#define MALI_DDK_GATOR_API_VERSION 3
-
-#if !defined(MALI_TRUE)
-       #define MALI_TRUE                ((uint32_t)1)
-#endif
-
-#if !defined(MALI_FALSE)
-       #define MALI_FALSE               ((uint32_t)0)
-#endif
-
-enum hwc_type {
-       JM_BLOCK = 0,
-       TILER_BLOCK,
-       SHADER_BLOCK,
-       MMU_L2_BLOCK,
-       RESERVED_BLOCK
-};
-
-struct kbase_gator_hwcnt_info {
-
-       /* Passed from Gator to kbase */
-
-       /* the bitmask of enabled hardware counters for each counter block */
-       uint16_t bitmask[4];
-
-       /* Passed from kbase to Gator */
-
-       /* ptr to counter dump memory */
-       void *kernel_dump_buffer;
-
-       /* size of counter dump memory */
-       uint32_t size;
-
-       /* the ID of the Mali device */
-       uint32_t gpu_id;
-
-       /* the number of shader cores in the GPU */
-       uint32_t nr_cores;
-
-       /* the number of core groups */
-       uint32_t nr_core_groups;
-
-       /* the memory layout of the performance counters */
-       enum hwc_type *hwc_layout;
-
-       /* the total number of hardware couter blocks */
-       uint32_t nr_hwc_blocks;
-};
-
-/**
- * @brief Opaque block of Mali data which Gator needs to return to the API later.
- */
-struct kbase_gator_hwcnt_handles;
-
-/**
- * @brief Initialize the resources Gator needs for performance profiling.
- *
- * @param in_out_info   A pointer to a structure containing the enabled counters passed from Gator and all the Mali
- *                      specific information that will be returned to Gator. On entry Gator must have populated the
- *                      'bitmask' field with the counters it wishes to enable for each class of counter block.
- *                      Each entry in the array corresponds to a single counter class based on the "hwc_type"
- *                      enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables
- *                      the first 4 counters in the block, and so on). See the GPU counter array as returned by
- *                      kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU.
- *
- * @return              Pointer to an opaque handle block on success, NULL on error.
- */
-extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info);
-
-/**
- * @brief Free all resources once Gator has finished using performance counters.
- *
- * @param in_out_info       A pointer to a structure containing the enabled counters passed from Gator and all the
- *                          Mali specific information that will be returned to Gator.
- * @param opaque_handles    A wrapper structure for kbase structures.
- */
-extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles);
-
-/**
- * @brief Poll whether a counter dump is successful.
- *
- * @param opaque_handles    A wrapper structure for kbase structures.
- * @param[out] success      Non-zero on success, zero on failure.
- *
- * @return                  Zero if the dump is still pending, non-zero if the dump has completed. Note that a
- *                          completed dump may not have dumped succesfully, so the caller must test for both
- *                          a completed and successful dump before processing counters.
- */
-extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success);
-
-/**
- * @brief Request the generation of a new counter dump.
- *
- * @param opaque_handles    A wrapper structure for kbase structures.
- *
- * @return                  Zero if the hardware device is busy and cannot handle the request, non-zero otherwise.
- */
-extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles);
-
-/**
- * @brief This function is used to fetch the names table based on the Mali device in use.
- *
- * @param[out] total_number_of_counters The total number of counters short names in the Mali devices' list.
- *
- * @return                              Pointer to an array of strings of length *total_number_of_counters.
- */
-extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_number_of_counters);
-
-/**
- * @brief This function is used to terminate the use of the names table.
- *
- * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value.
- */
-extern void kbase_gator_hwcnt_term_names(void);
-
-#endif
index 2bc0b037eee6c668e5948a4751678324dafb92a9..a5d1651573963368234d36dce02cc1980dcee6f6 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index d6465312628ed1a5479fff8611271201dc997749..f550490c2c39d4ac4df2ee70821907422d4e2278 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 1b784d5c3d589f0bbf06c64c858643179fcd6250..b0076c22da6be62323438bde5ba69a6ed436dcfc 100644 (file)
@@ -23,6 +23,7 @@ endif
 
 ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_kbase_gator_api.h),)
 EXTRA_CFLAGS += -DMALI_SIMPLE_API=1
+EXTRA_CFLAGS += -I$(DDK_DIR)/drivers/gpu/arm/midgard
 endif
 
 UMP_DIR = $(DDK_DIR)/include/linux
index 931bdf3d020580521ca25ad1d77f83a217db3d78..9002122c52aeb2d7e62788a3867e8c767f26a73f 100644 (file)
@@ -752,6 +752,7 @@ static struct class gpio_class = {
  */
 static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
 {
+       struct gpio_chip        *chip;
        unsigned long           flags;
        int                     status;
        const char              *ioname = NULL;
@@ -769,8 +770,16 @@ static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
                return -EINVAL;
        }
 
+       chip = desc->chip;
+
        mutex_lock(&sysfs_lock);
 
+       /* check if chip is being removed */
+       if (!chip || !chip->exported) {
+               status = -ENODEV;
+               goto fail_unlock;
+       }
+
        spin_lock_irqsave(&gpio_lock, flags);
        if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
             test_bit(FLAG_EXPORT, &desc->flags)) {
@@ -1040,6 +1049,8 @@ static void gpiochip_unexport(struct gpio_chip *chip)
 {
        int                     status;
        struct device           *dev;
+       struct gpio_desc *desc;
+       unsigned int i;
 
        mutex_lock(&sysfs_lock);
        dev = class_find_device(&gpio_class, NULL, chip, match_export);
@@ -1047,6 +1058,7 @@ static void gpiochip_unexport(struct gpio_chip *chip)
                sysfs_remove_group(&dev->kobj, &gpiochip_attr_group);
                put_device(dev);
                device_unregister(dev);
+               /* prevent further gpiod exports */
                chip->exported = 0;
                status = 0;
        } else
@@ -1056,6 +1068,13 @@ static void gpiochip_unexport(struct gpio_chip *chip)
        if (status)
                pr_debug("%s: chip %s status %d\n", __func__,
                                chip->label, status);
+
+       /* unregister gpiod class devices owned by sysfs */
+       for (i = 0; i < chip->ngpio; i++) {
+               desc = &chip->desc[i];
+               if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
+                       gpiod_free(desc);
+       }
 }
 
 static int __init gpiolib_sysfs_init(void)
@@ -1267,6 +1286,8 @@ int gpiochip_remove(struct gpio_chip *chip)
        int             status = 0;
        unsigned        id;
 
+       gpiochip_unexport(chip);
+
        spin_lock_irqsave(&gpio_lock, flags);
 
        gpiochip_remove_pin_ranges(chip);
@@ -1287,9 +1308,6 @@ int gpiochip_remove(struct gpio_chip *chip)
 
        spin_unlock_irqrestore(&gpio_lock, flags);
 
-       if (status == 0)
-               gpiochip_unexport(chip);
-
        return status;
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
index 7695b5dd9d2d3d95106d2658b175434e691db0d3..35287ab445cd9ef2a88b410c5ed1566b335e08c0 100644 (file)
 #define   GMBUS_CYCLE_INDEX    (2<<25)
 #define   GMBUS_CYCLE_STOP     (4<<25)
 #define   GMBUS_BYTE_COUNT_SHIFT 16
+#define   GMBUS_BYTE_COUNT_MAX   256U
 #define   GMBUS_SLAVE_INDEX_SHIFT 8
 #define   GMBUS_SLAVE_ADDR_SHIFT 1
 #define   GMBUS_SLAVE_READ     (1<<0)
index 639fe192997cdecb602c789f97045aad61328249..4a21e13cc58c15461191bb5980ee7de68e5a7f79 100644 (file)
@@ -276,18 +276,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
 }
 
 static int
-gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
-               u32 gmbus1_index)
+gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
+                     unsigned short addr, u8 *buf, unsigned int len,
+                     u32 gmbus1_index)
 {
        int reg_offset = dev_priv->gpio_mmio_base;
-       u16 len = msg->len;
-       u8 *buf = msg->buf;
 
        I915_WRITE(GMBUS1 + reg_offset,
                   gmbus1_index |
                   GMBUS_CYCLE_WAIT |
                   (len << GMBUS_BYTE_COUNT_SHIFT) |
-                  (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  (addr << GMBUS_SLAVE_ADDR_SHIFT) |
                   GMBUS_SLAVE_READ | GMBUS_SW_RDY);
        while (len) {
                int ret;
@@ -309,11 +308,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
 }
 
 static int
-gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
+               u32 gmbus1_index)
 {
-       int reg_offset = dev_priv->gpio_mmio_base;
-       u16 len = msg->len;
        u8 *buf = msg->buf;
+       unsigned int rx_size = msg->len;
+       unsigned int len;
+       int ret;
+
+       do {
+               len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+
+               ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
+                                           buf, len, gmbus1_index);
+               if (ret)
+                       return ret;
+
+               rx_size -= len;
+               buf += len;
+       } while (rx_size != 0);
+
+       return 0;
+}
+
+static int
+gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
+                      unsigned short addr, u8 *buf, unsigned int len)
+{
+       int reg_offset = dev_priv->gpio_mmio_base;
+       unsigned int chunk_size = len;
        u32 val, loop;
 
        val = loop = 0;
@@ -325,8 +348,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
        I915_WRITE(GMBUS3 + reg_offset, val);
        I915_WRITE(GMBUS1 + reg_offset,
                   GMBUS_CYCLE_WAIT |
-                  (msg->len << GMBUS_BYTE_COUNT_SHIFT) |
-                  (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  (chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
+                  (addr << GMBUS_SLAVE_ADDR_SHIFT) |
                   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
        while (len) {
                int ret;
@@ -343,6 +366,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
                if (ret)
                        return ret;
        }
+
+       return 0;
+}
+
+static int
+gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+{
+       u8 *buf = msg->buf;
+       unsigned int tx_size = msg->len;
+       unsigned int len;
+       int ret;
+
+       do {
+               len = min(tx_size, GMBUS_BYTE_COUNT_MAX);
+
+               ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len);
+               if (ret)
+                       return ret;
+
+               buf += len;
+               tx_size -= len;
+       } while (tx_size != 0);
+
        return 0;
 }
 
index f5d1dc5b5563b7fe466c27ddd4a10936cdbfe63b..54ebfbe370c6f5571917f63509d64dec182b78e3 100644 (file)
@@ -1007,12 +1007,28 @@ static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
 static const struct dmi_system_id intel_dual_link_lvds[] = {
        {
                .callback = intel_dual_link_lvds_callback,
-               .ident = "Apple MacBook Pro (Core i5/i7 Series)",
+               .ident = "Apple MacBook Pro 15\" (2010)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),
+               },
+       },
+       {
+               .callback = intel_dual_link_lvds_callback,
+               .ident = "Apple MacBook Pro 15\" (2011)",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
                        DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
                },
        },
+       {
+               .callback = intel_dual_link_lvds_callback,
+               .ident = "Apple MacBook Pro 15\" (2012)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),
+               },
+       },
        { }     /* terminating entry */
 };
 
index 971dd8795b68930fb512c3f2a87de04d72bd5db3..8ac333094991d8939415570cdde76ed597b9388d 100644 (file)
@@ -312,8 +312,10 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
                misc |= ATOM_COMPOSITESYNC;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                misc |= ATOM_INTERLACE;
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                misc |= ATOM_DOUBLE_CLOCK_MODE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
@@ -356,8 +358,10 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
                misc |= ATOM_COMPOSITESYNC;
        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
                misc |= ATOM_INTERLACE;
-       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
                misc |= ATOM_DOUBLE_CLOCK_MODE;
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
 
        args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
        args.ucCRTC = radeon_crtc->crtc_id;
index b131520521e456b433012b7b1d1c58f9f3cb4ad0..72b02483ff037dc376e18e250c4ba3c345c90e77 100644 (file)
@@ -76,7 +76,7 @@ static bool igp_read_bios_from_vram(struct radeon_device *rdev)
 
 static bool radeon_read_bios(struct radeon_device *rdev)
 {
-       uint8_t __iomem *bios;
+       uint8_t __iomem *bios, val1, val2;
        size_t size;
 
        rdev->bios = NULL;
@@ -86,15 +86,19 @@ static bool radeon_read_bios(struct radeon_device *rdev)
                return false;
        }
 
-       if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+       val1 = readb(&bios[0]);
+       val2 = readb(&bios[1]);
+
+       if (size == 0 || val1 != 0x55 || val2 != 0xaa) {
                pci_unmap_rom(rdev->pdev, bios);
                return false;
        }
-       rdev->bios = kmemdup(bios, size, GFP_KERNEL);
+       rdev->bios = kzalloc(size, GFP_KERNEL);
        if (rdev->bios == NULL) {
                pci_unmap_rom(rdev->pdev, bios);
                return false;
        }
+       memcpy_fromio(rdev->bios, bios, size);
        pci_unmap_rom(rdev->pdev, bios);
        return true;
 }
index 92f34de7aee93f78ec582996dd281533059b82f8..05e6a7d13d4e06e39f9cc6b52f347336f645bcf4 100644 (file)
@@ -169,7 +169,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto error0;
+               goto error_gpadl;
        }
 
        init_completion(&open_info->waitevent);
@@ -185,7 +185,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto error0;
+               goto error_gpadl;
        }
 
        if (userdatalen)
@@ -226,6 +226,9 @@ error1:
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
+error_gpadl:
+       vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
+
 error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
index 21ef68934a20bba366c1ea1c5be9705f0fafe6fa..edf8995cb3b3c7f8fd6af87f881ec654a91db975 100644 (file)
@@ -648,7 +648,7 @@ int vmbus_request_offers(void)
 {
        struct vmbus_channel_message_header *msg;
        struct vmbus_channel_msginfo *msginfo;
-       int ret, t;
+       int ret;
 
        msginfo = kmalloc(sizeof(*msginfo) +
                          sizeof(struct vmbus_channel_message_header),
@@ -656,8 +656,6 @@ int vmbus_request_offers(void)
        if (!msginfo)
                return -ENOMEM;
 
-       init_completion(&msginfo->waitevent);
-
        msg = (struct vmbus_channel_message_header *)msginfo->msg;
 
        msg->msgtype = CHANNELMSG_REQUESTOFFERS;
@@ -671,14 +669,6 @@ int vmbus_request_offers(void)
                goto cleanup;
        }
 
-       t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
-       if (t == 0) {
-               ret = -ETIMEDOUT;
-               goto cleanup;
-       }
-
-
-
 cleanup:
        kfree(msginfo);
 
index c1f8ccd40b15dbf283772c062f58f3bf9c4bf5b0..e3a4f744a791a87cf24055b93131e8a1933b26f1 100755 (executable)
@@ -214,6 +214,7 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
        adap->bus_recovery_info->set_scl(adap, 1);
        return i2c_generic_recovery(adap);
 }
+EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery);
 
 int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
 {
@@ -228,6 +229,7 @@ int i2c_generic_gpio_recovery(struct i2c_adapter *adap)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(i2c_generic_gpio_recovery);
 
 int i2c_recover_bus(struct i2c_adapter *adap)
 {
@@ -237,6 +239,7 @@ int i2c_recover_bus(struct i2c_adapter *adap)
        dev_dbg(&adap->dev, "Trying i2c bus recovery\n");
        return adap->bus_recovery_info->recover_bus(adap);
 }
+EXPORT_SYMBOL_GPL(i2c_recover_bus);
 
 static int i2c_device_probe(struct device *dev)
 {
index e0017c22bb9c6ce3b4f4f9c753a8ce1364621b19..f53e9a803a0e1ec1589a5b0ad25d7aa1f8d54e70 100644 (file)
@@ -60,7 +60,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
        iio_trigger_set_drvdata(adis->trig, adis);
        ret = iio_trigger_register(adis->trig);
 
-       indio_dev->trig = adis->trig;
+       indio_dev->trig = iio_trigger_get(adis->trig);
        if (ret)
                goto error_free_irq;
 
index 7da0832f187b8d320cd8618eb3379b2015bee927..01d661e0fa6cd81535fc069a8a339916d233978d 100644 (file)
 #include <linux/poll.h>
 #include "inv_mpu_iio.h"
 
+static void inv_clear_kfifo(struct inv_mpu6050_state *st)
+{
+       unsigned long flags;
+
+       /* take the spin lock sem to avoid interrupt kick in */
+       spin_lock_irqsave(&st->time_stamp_lock, flags);
+       kfifo_reset(&st->timestamps);
+       spin_unlock_irqrestore(&st->time_stamp_lock, flags);
+}
+
 int inv_reset_fifo(struct iio_dev *indio_dev)
 {
        int result;
@@ -51,6 +61,10 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
                                        INV_MPU6050_BIT_FIFO_RST);
        if (result)
                goto reset_fifo_fail;
+
+       /* clear timestamps fifo */
+       inv_clear_kfifo(st);
+
        /* enable interrupt */
        if (st->chip_config.accl_fifo_enable ||
            st->chip_config.gyro_fifo_enable) {
@@ -84,16 +98,6 @@ reset_fifo_fail:
        return result;
 }
 
-static void inv_clear_kfifo(struct inv_mpu6050_state *st)
-{
-       unsigned long flags;
-
-       /* take the spin lock sem to avoid interrupt kick in */
-       spin_lock_irqsave(&st->time_stamp_lock, flags);
-       kfifo_reset(&st->timestamps);
-       spin_unlock_irqrestore(&st->time_stamp_lock, flags);
-}
-
 /**
  * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
  */
@@ -187,7 +191,6 @@ end_session:
 flush_fifo:
        /* Flush HW and SW FIFOs. */
        inv_reset_fifo(indio_dev);
-       inv_clear_kfifo(st);
        mutex_unlock(&indio_dev->mlock);
        iio_trigger_notify_done(indio_dev->trig);
 
index a84112322071015a78b7916bfe70250284f1640e..c1fef27010d45203ef0f87334227ef7535b5d345 100644 (file)
@@ -94,6 +94,17 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
        if (dmasync)
                dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
 
+       if (!size)
+               return ERR_PTR(-EINVAL);
+
+       /*
+        * If the combination of the addr and size requested for this memory
+        * region causes an integer overflow, return error.
+        */
+       if (((addr + size) < addr) ||
+           PAGE_ALIGN(addr + size) < (addr + size))
+               return ERR_PTR(-EINVAL);
+
        if (!can_do_mlock())
                return ERR_PTR(-EPERM);
 
index 2c6f0f2ecd9d84ee5f3ae4e29f1636b3f863047a..949b386334964a07a68512152230df05da6a4c8c 100644 (file)
@@ -460,6 +460,7 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
 
        entry->desc.async.element    = element;
        entry->desc.async.event_type = event;
+       entry->desc.async.reserved   = 0;
        entry->counter               = counter;
 
        list_add_tail(&entry->list, &file->async_file->event_list);
index 4d599cedbb0b1ccceab997a4945be0d8d6e89fde..6ee534874535729a389de8808922332696be0f5f 100644 (file)
@@ -64,6 +64,14 @@ enum {
 #define GUID_TBL_BLK_NUM_ENTRIES 8
 #define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES)
 
+/* Counters should be saturate once they reach their maximum value */
+#define ASSIGN_32BIT_COUNTER(counter, value) do {\
+       if ((value) > U32_MAX)                   \
+               counter = cpu_to_be32(U32_MAX); \
+       else                                     \
+               counter = cpu_to_be32(value);    \
+} while (0)
+
 struct mlx4_mad_rcv_buf {
        struct ib_grh grh;
        u8 payload[256];
@@ -730,10 +738,14 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 static void edit_counter(struct mlx4_counter *cnt,
                                        struct ib_pma_portcounters *pma_cnt)
 {
-       pma_cnt->port_xmit_data = cpu_to_be32((be64_to_cpu(cnt->tx_bytes)>>2));
-       pma_cnt->port_rcv_data  = cpu_to_be32((be64_to_cpu(cnt->rx_bytes)>>2));
-       pma_cnt->port_xmit_packets = cpu_to_be32(be64_to_cpu(cnt->tx_frames));
-       pma_cnt->port_rcv_packets  = cpu_to_be32(be64_to_cpu(cnt->rx_frames));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_data,
+                            (be64_to_cpu(cnt->tx_bytes) >> 2));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_data,
+                            (be64_to_cpu(cnt->rx_bytes) >> 2));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_xmit_packets,
+                            be64_to_cpu(cnt->tx_frames));
+       ASSIGN_32BIT_COUNTER(pma_cnt->port_rcv_packets,
+                            be64_to_cpu(cnt->rx_frames));
 }
 
 static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
index 4f10af2905b505e1b9ae5c8a2ab13a634cdc4b4a..262a18437ceb00f2a5a96b3be5dc126c3fb08453 100644 (file)
@@ -2174,8 +2174,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
 
        memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
 
-       *lso_hdr_sz  = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
-                                  wr->wr.ud.hlen);
+       *lso_hdr_sz  = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
        *lso_seg_len = halign;
        return 0;
 }
index 85e75239c81404f9e31b92b8fad2779a095bdb00..1af7df2633684ebb31872cd07bce225b4054a397 100644 (file)
@@ -783,6 +783,21 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
        return PSMOUSE_FULL_PACKET;
 }
 
+/*
+ * This writes the reg_07 value again to the hardware at the end of every
+ * set_rate call because the register loses its value. reg_07 allows setting
+ * absolute mode on v4 hardware
+ */
+static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse,
+               unsigned int rate)
+{
+       struct elantech_data *etd = psmouse->private;
+
+       etd->original_set_rate(psmouse, rate);
+       if (elantech_write_reg(psmouse, 0x07, etd->reg_07))
+               psmouse_err(psmouse, "restoring reg_07 failed\n");
+}
+
 /*
  * Put the touchpad into absolute mode
  */
@@ -985,6 +1000,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus K53SV              0x450f01        78, 15, 0c      2 hw buttons
  * Asus G46VW              0x460f02        00, 18, 0c      2 hw buttons
  * Asus G750JX             0x360f00        00, 16, 0c      2 hw buttons
+ * Asus TP500LN            0x381f17        10, 14, 0e      clickpad
+ * Asus X750JN             0x381f17        10, 14, 0e      clickpad
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
@@ -1452,6 +1469,11 @@ int elantech_init(struct psmouse *psmouse)
                goto init_fail;
        }
 
+       if (etd->fw_version == 0x381f17) {
+               etd->original_set_rate = psmouse->set_rate;
+               psmouse->set_rate = elantech_set_rate_restore_reg_07;
+       }
+
        if (elantech_set_input_params(psmouse)) {
                psmouse_err(psmouse, "failed to query touchpad range.\n");
                goto init_fail;
index c1c15ab6872d79743e97798bb6c7c5dcf760aa0f..13a12ccbff51e0f0db0a1a1b07ebe09ec847a817 100644 (file)
@@ -138,6 +138,7 @@ struct elantech_data {
        struct finger_pos mt[ETP_MAX_FINGERS];
        unsigned char parity[256];
        int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param);
+       void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate);
 };
 
 #ifdef CONFIG_MOUSE_PS2_ELANTECH
index f804c1faa7ffffe31ab19bf17acd25874f69d74b..d3b54f7b849febdde772af52d41986e5abdcb8bc 100644 (file)
@@ -29,7 +29,7 @@
 
 /* Offset base used to differentiate between CAPTURE and OUTPUT
 *  while mmaping */
-#define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
+#define DST_QUEUE_OFF_BASE     (1 << 30)
 
 #define MFC_BANK1_ALLOC_CTX    0
 #define MFC_BANK2_ALLOC_CTX    1
index a59153d2f8bfd11dbf1f3f681ef6548bd3b7ecad..518a5299ff0b63f9457da042c697d5beba432243 100644 (file)
@@ -245,6 +245,11 @@ static int stk1160_stop_streaming(struct stk1160 *dev)
        if (mutex_lock_interruptible(&dev->v4l_lock))
                return -ERESTARTSYS;
 
+       /*
+        * Once URBs are cancelled, the URB complete handler
+        * won't be running. This is required to safely release the
+        * current buffer (dev->isoc_ctl.buf).
+        */
        stk1160_cancel_isoc(dev);
 
        /*
@@ -665,8 +670,16 @@ void stk1160_clear_queue(struct stk1160 *dev)
                stk1160_info("buffer [%p/%d] aborted\n",
                                buf, buf->vb.v4l2_buf.index);
        }
-       /* It's important to clear current buffer */
-       dev->isoc_ctl.buf = NULL;
+
+       /* It's important to release the current buffer */
+       if (dev->isoc_ctl.buf) {
+               buf = dev->isoc_ctl.buf;
+               dev->isoc_ctl.buf = NULL;
+
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               stk1160_info("buffer [%p/%d] aborted\n",
+                               buf, buf->vb.v4l2_buf.index);
+       }
        spin_unlock_irqrestore(&dev->buf_lock, flags);
 }
 
index f4176ca3a794ee2c684d35e3461da165b1abc7ce..cdd61ab5c2b57885f4398896e4b1dc4cfedae668 100644 (file)
@@ -758,7 +758,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
 
                if (error || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
                        if (msb->data_dir == READ) {
-                               for (cnt = 0; cnt < msb->current_seg; cnt++)
+                               for (cnt = 0; cnt < msb->current_seg; cnt++) {
                                        t_len += msb->req_sg[cnt].length
                                                 / msb->page_size;
 
@@ -766,6 +766,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error)
                                                t_len += msb->current_page - 1;
 
                                        t_len *= msb->page_size;
+                               }
                        }
                } else
                        t_len = blk_rq_bytes(msb->block_req);
index 6df820652d6d85096a9cf44da5272dae3953d582..355c18f4aa39ddb480a0be90b0791177ad083bd2 100755 (executable)
@@ -952,6 +952,18 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
        md->reset_done &= ~type;
 }
 
+int mmc_access_rpmb(struct mmc_queue *mq)
+{
+       struct mmc_blk_data *md = mq->data;
+       /*
+        * If this is a RPMB partition access, return ture
+        */
+       if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+               return true;
+
+       return false;
+}
+
 static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
 {
        struct mmc_blk_data *md = mq->data;
index 3e049c13429cfbe730179724053796cc65ba62de..6ceede0a0bf798c6947d89a7a4993c3490465550 100644 (file)
@@ -38,7 +38,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req)
                return BLKPREP_KILL;
        }
 
-       if (mq && mmc_card_removed(mq->card))
+       if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
                return BLKPREP_KILL;
 
        req->cmd_flags |= REQ_DONTPREP;
index 5752d50049a34c2a9ee8f6585105990f1e018d05..99e6521e61696202c036dfb00fe6bdcd96c0f613 100644 (file)
@@ -73,4 +73,6 @@ extern void mmc_queue_bounce_post(struct mmc_queue_req *);
 extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *);
 extern void mmc_packed_clean(struct mmc_queue *);
 
+extern int mmc_access_rpmb(struct mmc_queue *);
+
 #endif
index c071d410488f4c95a25ef4a4fedfc325b5ff83c9..79d69bd26dd258d74163b7aafb78cecdd6b448ff 100644 (file)
@@ -408,7 +408,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
                second_is_newer = !second_is_newer;
        } else {
                dbg_bld("PEB %d CRC is OK", pnum);
-               bitflips = !!err;
+               bitflips |= !!err;
        }
        mutex_unlock(&ubi->buf_mutex);
 
index 4f02848bb2bc5d843900d6762b10edec23e3dd84..fc764e7976bdf9d79ceeba38ddbf33975c81edc7 100644 (file)
@@ -475,7 +475,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
                /* Validate the request */
                err = -EINVAL;
                if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
-                   req.bytes < 0 || req.lnum >= vol->usable_leb_size)
+                   req.bytes < 0 || req.bytes > vol->usable_leb_size)
                        break;
 
                err = get_exclusive(desc);
index 0e11671dadc48c129c3f9cd669c8cf7c9ec5bf70..930cf2c77abb14a386610a56de9c7eabed6b9598 100644 (file)
@@ -1362,7 +1362,8 @@ int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                                 * during re-size.
                                 */
                                ubi_move_aeb_to_list(av, aeb, &ai->erase);
-                       vol->eba_tbl[aeb->lnum] = aeb->pnum;
+                       else
+                               vol->eba_tbl[aeb->lnum] = aeb->pnum;
                }
        }
 
index f913d701a5b3d96222ca9eeb71007c6ee982e209..c4b1af07a121963b06dd7cd71826b14d639e14ee 100644 (file)
@@ -74,6 +74,8 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
        for (i = 0; i < vol->used_ebs; i++) {
                int size;
 
+               cond_resched();
+
                if (i == vol->used_ebs - 1)
                        size = vol->last_eb_bytes;
                else
index 49e570abe58b01b07a3e78e71d0fede9fd99306a..c08254016fe8b34d495793de03ffdd589e894a00 100644 (file)
@@ -999,7 +999,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                                int cancel)
 {
        int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
-       int vol_id = -1, uninitialized_var(lnum);
+       int vol_id = -1, lnum = -1;
 #ifdef CONFIG_MTD_UBI_FASTMAP
        int anchor = wrk->anchor;
 #endif
index 5d204492c603a84fd94f03faf5fc1179abf61208..161dcba13c479b1fa7260aa144d5344d73fa83e5 100644 (file)
@@ -2869,7 +2869,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                sw_cons = BNX2_NEXT_TX_BD(sw_cons);
 
                tx_bytes += skb->len;
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                tx_pkt++;
                if (tx_pkt == budget)
                        break;
@@ -6610,7 +6610,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        mapping = dma_map_single(&bp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE);
        if (dma_mapping_error(&bp->pdev->dev, mapping)) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
@@ -6703,7 +6703,7 @@ dma_error:
                               PCI_DMA_TODEVICE);
        }
 
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
 }
 
index 8c1eab1151b859b23ff01e0e2fb137c1e9b96c14..680d26d6d2c308a3314b8b3c78ec7b356d65a74d 100644 (file)
@@ -6437,7 +6437,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
                pkts_compl++;
                bytes_compl += skb->len;
 
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
 
                if (unlikely(tx_bug)) {
                        tg3_tx_recover(tp);
@@ -6769,7 +6769,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                if (len > (tp->dev->mtu + ETH_HLEN) &&
                    skb->protocol != htons(ETH_P_8021Q) &&
                    skb->protocol != htons(ETH_P_8021AD)) {
-                       dev_kfree_skb(skb);
+                       dev_kfree_skb_any(skb);
                        goto drop_it_no_recycle;
                }
 
@@ -7652,7 +7652,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                                          PCI_DMA_TODEVICE);
                /* Make sure the mapping succeeded */
                if (pci_dma_mapping_error(tp->pdev, new_addr)) {
-                       dev_kfree_skb(new_skb);
+                       dev_kfree_skb_any(new_skb);
                        ret = -1;
                } else {
                        u32 save_entry = *entry;
@@ -7667,13 +7667,13 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                                            new_skb->len, base_flags,
                                            mss, vlan)) {
                                tg3_tx_skb_unmap(tnapi, save_entry, -1);
-                               dev_kfree_skb(new_skb);
+                               dev_kfree_skb_any(new_skb);
                                ret = -1;
                        }
                }
        }
 
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        *pskb = new_skb;
        return ret;
 }
@@ -7716,7 +7716,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
        } while (segs);
 
 tg3_tso_bug_end:
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 
        return NETDEV_TX_OK;
 }
@@ -7954,7 +7954,7 @@ dma_error:
        tg3_tx_skb_unmap(tnapi, tnapi->tx_prod, --i);
        tnapi->tx_buffers[tnapi->tx_prod].skb = NULL;
 drop:
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 drop_nofree:
        tp->tx_dropped++;
        return NETDEV_TX_OK;
index d81a7dbfeef606e79365ac61750fab49e8ca6b8b..88e85cb88342cea8a5810412df04de3a9a488141 100644 (file)
@@ -1767,7 +1767,7 @@ static u16 be_tx_compl_process(struct be_adapter *adapter,
                queue_tail_inc(txq);
        } while (cur_index != last_index);
 
-       kfree_skb(sent_skb);
+       dev_kfree_skb_any(sent_skb);
        return num_wrbs;
 }
 
index 59ad007dd5aa09a6123cbd25db7c7b8f4e06f1b7..a978fc82ceb584221e6a2f29d90d5ab89c04c860 100644 (file)
@@ -144,6 +144,11 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
                                     struct e1000_rx_ring *rx_ring,
                                     int *work_done, int work_to_do);
+static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter,
+                                        struct e1000_rx_ring *rx_ring,
+                                        int cleaned_count)
+{
+}
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
                                   struct e1000_rx_ring *rx_ring,
                                   int cleaned_count);
@@ -3555,8 +3560,11 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
                msleep(1);
        /* e1000_down has a dependency on max_frame_size */
        hw->max_frame_size = max_frame;
-       if (netif_running(netdev))
+       if (netif_running(netdev)) {
+               /* prevent buffers from being reallocated */
+               adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers;
                e1000_down(adapter);
+       }
 
        /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
         * means we reserve 2 more, this pushes us to allocate from the next
index fce3e92f9d11cf249b9574d3687947f3242dd81e..c5a9dcc01ca8ac8ebc6e558a7c9b56f9c132fb1b 100644 (file)
@@ -1527,12 +1527,12 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        int tso;
 
        if (test_bit(__IXGB_DOWN, &adapter->flags)) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
        if (skb->len <= 0) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
@@ -1549,7 +1549,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        tso = ixgb_tso(adapter, skb);
        if (tso < 0) {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
index 064425d3178ddc32e852dcde418785284b938d2b..437d4cfd42cc740580681e499b27a0dc7c350368 100644 (file)
@@ -899,7 +899,7 @@ out_unlock:
 
        return NETDEV_TX_OK;
 out_dma_error:
-       kfree_skb(skb);
+       dev_kfree_skb_any(skb);
        cp->dev->stats.tx_dropped++;
        goto out_unlock;
 }
index 3ccedeb8aba03703bcdff318dff2ff888eec4bfa..942673fcb391f491d91269db284d0ab6537a7523 100644 (file)
@@ -1715,9 +1715,9 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
                if (len < ETH_ZLEN)
                        memset(tp->tx_buf[entry], 0, ETH_ZLEN);
                skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
        } else {
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(skb);
                dev->stats.tx_dropped++;
                return NETDEV_TX_OK;
        }
index e9b5d77a90dbf90491de74721e67a4ab4bb3bfd7..2183c618914843d30ef2dd7bcbfebcc529c8ddf4 100644 (file)
@@ -5768,7 +5768,7 @@ static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
                                             tp->TxDescArray + entry);
                        if (skb) {
                                tp->dev->stats.tx_dropped++;
-                               dev_kfree_skb(skb);
+                               dev_kfree_skb_any(skb);
                                tx_skb->skb = NULL;
                        }
                }
@@ -5993,7 +5993,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 err_dma_1:
        rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
 err_dma_0:
-       dev_kfree_skb(skb);
+       dev_kfree_skb_any(skb);
 err_update_stats:
        dev->stats.tx_dropped++;
        return NETDEV_TX_OK;
@@ -6076,7 +6076,7 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
                        tp->tx_stats.packets++;
                        tp->tx_stats.bytes += tx_skb->skb->len;
                        u64_stats_update_end(&tp->tx_stats.syncp);
-                       dev_kfree_skb(tx_skb->skb);
+                       dev_kfree_skb_any(tx_skb->skb);
                        tx_skb->skb = NULL;
                }
                dirty_tx++;
index 71ea77576d222cc0154d062d42d53191a8c4fc67..e783ea0e383790995513430e44ec228e1ce3379f 100644 (file)
@@ -670,7 +670,6 @@ struct iwl_priv {
        unsigned long reload_jiffies;
        int reload_count;
        bool ucode_loaded;
-       bool init_ucode_run;            /* Don't run init uCode again */
 
        u8 plcp_delta_threshold;
 
index 0a1cdc5e856baa6f37966cac3021d9db2558c6a9..5ad94a8080b834e5086f09f8fabb13d62aa8078f 100644 (file)
@@ -425,9 +425,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
        if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len)
                return 0;
 
-       if (priv->init_ucode_run)
-               return 0;
-
        iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
                                   calib_complete, ARRAY_SIZE(calib_complete),
                                   iwlagn_wait_calib, priv);
@@ -447,8 +444,6 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
         */
        ret = iwl_wait_notification(&priv->notif_wait, &calib_wait,
                                        UCODE_CALIB_TIMEOUT);
-       if (!ret)
-               priv->init_ucode_run = true;
 
        goto out;
 
index e7a2af3ad05a8b9e1034fe7abcf6738c087dd97a..7555095e0b74ce122208ac58a22edcf7d5a28236 100644 (file)
@@ -313,6 +313,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
        {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
        {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
+       {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
        {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
        {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
        {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
@@ -369,6 +370,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
        {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+       {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */
        {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
        {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/
        {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/
index 7f1669cdea090ed6895b8eaabf0ab7f74054d9c4..779dc2b2ca7591077e18494a4eaa3c82ed8f846d 100644 (file)
@@ -136,7 +136,7 @@ WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u");
 WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u");
 WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u");
 
-WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u");
+WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(rx_rate, rx_frames_per_rates, 50);
 
 WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate,
                                  AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE);
index f7381dd69009a150e1901a876494d225e0267f5e..1bce4325e86bba78bc808fb95eea3738bb9a6663 100644 (file)
@@ -26,8 +26,8 @@
 
 #include "wlcore.h"
 
-int wl1271_format_buffer(char __user *userbuf, size_t count,
-                        loff_t *ppos, char *fmt, ...);
+__printf(4, 5) int wl1271_format_buffer(char __user *userbuf, size_t count,
+                                       loff_t *ppos, char *fmt, ...);
 
 int wl1271_debugfs_init(struct wl1271 *wl);
 void wl1271_debugfs_exit(struct wl1271 *wl);
index a50576081b34dd998fbbd8aca4fd0c154df5420e..46d2de24bf3e190c0933eb11d2120a67d07d44b0 100644 (file)
@@ -36,7 +36,9 @@ if PARPORT
 config PARPORT_PC
        tristate "PC-style hardware"
        depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && !S390 && \
-               (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && !XTENSA
+               (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && \
+               !XTENSA && !CRIS && !H8300 && !ARM64
+
        ---help---
          You should say Y here if you have a PC-style parallel port. All
          IBM PC compatible computers and some Alphas have PC-style
index f962d98bd775222de9beb345638aadc86813b4b6..c10a08bc2093681b18457474e4411b5be9603989 100644 (file)
@@ -1077,7 +1077,7 @@ void devm_pinctrl_put(struct pinctrl *p)
 EXPORT_SYMBOL_GPL(devm_pinctrl_put);
 
 int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-                        bool dup, bool locked)
+                        bool dup)
 {
        int i, ret;
        struct pinctrl_maps *maps_node;
@@ -1145,11 +1145,9 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
                maps_node->maps = maps;
        }
 
-       if (!locked)
-               mutex_lock(&pinctrl_maps_mutex);
+       mutex_lock(&pinctrl_maps_mutex);
        list_add_tail(&maps_node->node, &pinctrl_maps);
-       if (!locked)
-               mutex_unlock(&pinctrl_maps_mutex);
+       mutex_unlock(&pinctrl_maps_mutex);
 
        return 0;
 }
@@ -1164,7 +1162,7 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
 int pinctrl_register_mappings(struct pinctrl_map const *maps,
                              unsigned num_maps)
 {
-       return pinctrl_register_map(maps, num_maps, true, false);
+       return pinctrl_register_map(maps, num_maps, true);
 }
 
 void pinctrl_unregister_map(struct pinctrl_map const *map)
index 75476b3d87dafe00c6273931a4e3a137f1509dfa..b24ea846c8677ebea49ffd435c04c3de40f226b9 100644 (file)
@@ -183,7 +183,7 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
 }
 
 int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-                        bool dup, bool locked);
+                        bool dup);
 void pinctrl_unregister_map(struct pinctrl_map const *map);
 
 extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev);
index 340fb4e6c600393f0504e6d6cd5f7adc9cbad29e..fd91c4c31f6b638f33a69e2052b60c7ad6f26f31 100644 (file)
@@ -92,7 +92,7 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
        dt_map->num_maps = num_maps;
        list_add_tail(&dt_map->node, &p->dt_maps);
 
-       return pinctrl_register_map(map, num_maps, false, true);
+       return pinctrl_register_map(map, num_maps, false);
 }
 
 struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
index ed49b50b220b3ed6541c5b6f82079e1d0373e8f7..72da2a6c22db953b1c9c95a84fc27a9007580891 100644 (file)
@@ -417,8 +417,10 @@ static int lp8788_psy_register(struct platform_device *pdev,
        pchg->battery.num_properties = ARRAY_SIZE(lp8788_battery_prop);
        pchg->battery.get_property = lp8788_battery_get_property;
 
-       if (power_supply_register(&pdev->dev, &pchg->battery))
+       if (power_supply_register(&pdev->dev, &pchg->battery)) {
+               power_supply_unregister(&pchg->charger);
                return -EPERM;
+       }
 
        return 0;
 }
index 0a7325361d2958dceeae99da5959e518f8490985..5f57e3d35e26d4aad0e3620759e7ee253bccce92 100644 (file)
@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
 static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
 
 /* Functions */
 
@@ -1352,11 +1351,11 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
                                }
 
                                /* Now complete the io */
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                                tw_dev->state[request_id] = TW_S_COMPLETED;
                                twa_free_request_id(tw_dev, request_id);
                                tw_dev->posted_request_count--;
-                               tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                               twa_unmap_scsi_data(tw_dev, request_id);
                        }
 
                        /* Check for valid status after each drain */
@@ -1414,26 +1413,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm
        }
 } /* End twa_load_sgl() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twa_map_scsi_sg_data() */
-
 /* This function will poll for a response interrupt of a request */
 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
 {
@@ -1612,9 +1591,11 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
                        if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twa_unmap_scsi_data(tw_dev, i);
+                               struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                               cmd->result = (DID_RESET << 16);
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1793,21 +1774,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        switch (retval) {
        case SCSI_MLQUEUE_HOST_BUSY:
+               scsi_dma_unmap(SCpnt);
                twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                break;
        case 1:
-               tw_dev->state[request_id] = TW_S_COMPLETED;
-               twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                SCpnt->result = (DID_ERROR << 16);
+               scsi_dma_unmap(SCpnt);
                done(SCpnt);
+               tw_dev->state[request_id] = TW_S_COMPLETED;
+               twa_free_request_id(tw_dev, request_id);
                retval = 0;
        }
 out:
@@ -1875,8 +1853,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                                command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
                                command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
                        } else {
-                               sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
-                               if (sg_count == 0)
+                               sg_count = scsi_dma_map(srb);
+                               if (sg_count < 0)
                                        goto out;
 
                                scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1991,15 +1969,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code)
        return(table[index].text);
 } /* End twa_string_lookup() */
 
-/* This function will perform a pci-dma unmap */
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twa_unmap_scsi_data() */
-
 /* This function gets called when a disk is coming on-line */
 static int twa_slave_configure(struct scsi_device *sdev)
 {
index 040f7214e5b7a5c3782743a4a66a456aea79df81..0fdc83cfa0e1a28a42757ae52f434523238075b3 100644 (file)
@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = {
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE  1
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_9550SX_DRAIN_COMPLETED            0xFFFF
 #define TW_SECTOR_SIZE                        512
index 4de346017e9ff91b43aed80d48231ac60f23a4e3..61702ac00d42f3632eec2e9a310d03d59667c5e2 100644 (file)
@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
        return 0;
 } /* End twl_post_command_packet() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twl_map_scsi_sg_data() */
-
 /* This function hands scsi cdb's to the firmware */
 static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
 {
@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
        if (!sglistarg) {
                /* Map sglist from scsi layer to cmd packet */
                if (scsi_sg_count(srb)) {
-                       sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
-                       if (sg_count == 0)
+                       sg_count = scsi_dma_map(srb);
+                       if (sg_count <= 0)
                                goto out;
 
                        scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1116,15 +1096,6 @@ out:
        return retval;
 } /* End twl_initialize_device_extension() */
 
-/* This function will perform a pci-dma unmap */
-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twl_unmap_scsi_data() */
-
 /* This function will handle attention interrupts */
 static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
 {
@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance)
                        }
 
                        /* Now complete the io */
+                       scsi_dma_unmap(cmd);
+                       cmd->scsi_done(cmd);
                        tw_dev->state[request_id] = TW_S_COMPLETED;
                        twl_free_request_id(tw_dev, request_id);
                        tw_dev->posted_request_count--;
-                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                       twl_unmap_scsi_data(tw_dev, request_id);
                }
 
                /* Check for another response interrupt */
@@ -1414,10 +1385,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
                if ((tw_dev->state[i] != TW_S_FINISHED) &&
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
-                       if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twl_unmap_scsi_data(tw_dev, i);
+                       struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                       if (cmd) {
+                               cmd->result = (DID_RESET << 16);
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        if (retval) {
                tw_dev->state[request_id] = TW_S_COMPLETED;
index d474892701d4540658a36b48edb7b903a8b9ba76..fec6449c7595132f706439277cd396b4dc66c0a8 100644 (file)
@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] =
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_SECTOR_SIZE                        512
 #define TW_MAX_UNITS                         32
index 430ee3774c3b62cfc51dbd9ee65b3da32cb624a9..8843ad783b41e59ecdab7efbdd2a5acbaae3857a 100644 (file)
@@ -1283,32 +1283,6 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
        return 0;
 } /* End tw_initialize_device_extension() */
 
-static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       int use_sg;
-
-       dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
-
-       use_sg = scsi_dma_map(cmd);
-       if (use_sg < 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End tw_map_scsi_sg_data() */
-
-static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End tw_unmap_scsi_data() */
-
 /* This function will reset a device extension */
 static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
 {
@@ -1331,8 +1305,8 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
                        srb = tw_dev->srb[i];
                        if (srb != NULL) {
                                srb->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
+                               scsi_dma_unmap(srb);
+                               srb->scsi_done(srb);
                        }
                }
        }
@@ -1779,8 +1753,8 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
        command_packet->byte8.io.lba = lba;
        command_packet->byte6.block_count = num_sectors;
 
-       use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-       if (!use_sg)
+       use_sg = scsi_dma_map(srb);
+       if (use_sg <= 0)
                return 1;
 
        scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
@@ -1967,9 +1941,6 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        switch (*command) {
                case READ_10:
                case READ_6:
@@ -2196,12 +2167,11 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance)
 
                                /* Now complete the io */
                                if ((error != TW_ISR_DONT_COMPLETE)) {
+                                       scsi_dma_unmap(tw_dev->srb[request_id]);
+                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                                        tw_dev->state[request_id] = TW_S_COMPLETED;
                                        tw_state_request_finish(tw_dev, request_id);
                                        tw_dev->posted_request_count--;
-                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                                       
-                                       tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
                                }
                        }
                                
index 49dcf03c631a52f971170d6ee029083a69edab34..1d31858766ce4b7e0fda8b569fed1850208c72c3 100644 (file)
@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] =
 #define TW_AEN_SMART_FAIL        0x000F
 #define TW_AEN_SBUF_FAIL         0x0024
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE 1
-#define TW_PHASE_SGLIST 2
-
 /* Misc defines */
 #define TW_ALIGNMENT_6000                    64 /* 64 bytes */
 #define TW_ALIGNMENT_7000                     4  /* 4 bytes */
index 1ad39c799c7413c7452804ece74a9de4f356fe7e..bfe812fcce3433bdaea31f0f9d78062d3133ffc6 100644 (file)
@@ -5080,9 +5080,9 @@ free_port:
 hba_free:
        if (phba->msix_enabled)
                pci_disable_msix(phba->pcidev);
-       iscsi_host_remove(phba->shost);
        pci_dev_put(phba->pcidev);
        iscsi_host_free(phba->shost);
+       pci_set_drvdata(pcidev, NULL);
 disable_pci:
        pci_disable_device(pcidev);
        return ret;
index c9e244984e30ec1dfed39c7b574b71caffeb0794..fa50c7dc3d3eb574f4a919766db9aa31aa18e9e3 100644 (file)
@@ -441,14 +441,11 @@ static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag)
 static int mvs_task_prep_ata(struct mvs_info *mvi,
                             struct mvs_task_exec_info *tei)
 {
-       struct sas_ha_struct *sha = mvi->sas;
        struct sas_task *task = tei->task;
        struct domain_device *dev = task->dev;
        struct mvs_device *mvi_dev = dev->lldd_dev;
        struct mvs_cmd_hdr *hdr = tei->hdr;
        struct asd_sas_port *sas_port = dev->port;
-       struct sas_phy *sphy = dev->phy;
-       struct asd_sas_phy *sas_phy = sha->sas_phy[sphy->number];
        struct mvs_slot_info *slot;
        void *buf_prd;
        u32 tag = tei->tag, hdr_tag;
@@ -468,7 +465,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
        slot->tx = mvi->tx_prod;
        del_q = TXQ_MODE_I | tag |
                (TXQ_CMD_STP << TXQ_CMD_SHIFT) |
-               (MVS_PHY_ID << TXQ_PHY_SHIFT) |
+               ((sas_port->phy_mask & TXQ_PHY_MASK) << TXQ_PHY_SHIFT) |
                (mvi_dev->taskfileset << TXQ_SRS_SHIFT);
        mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
 
index 26b898182e8f1939056c6f7cc8715b03e79a674e..d9bea57ea1fd8c3d4b04d2d3ae503dcdcc9a9f33 100644 (file)
@@ -1242,9 +1242,11 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
                                    "rejecting I/O to dead device\n");
                        ret = BLKPREP_KILL;
                        break;
-               case SDEV_QUIESCE:
                case SDEV_BLOCK:
                case SDEV_CREATED_BLOCK:
+                       ret = BLKPREP_DEFER;
+                       break;
+               case SDEV_QUIESCE:
                        /*
                         * If the devices is blocked we defer normal commands.
                         */
index a8990783ba66bad4038210f8a2d6d7372bbcd261..913b91c78a22ca04b04c6d84ec3f63a17745dfeb 100644 (file)
@@ -631,21 +631,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
                        if (bounce_sgl[j].length == PAGE_SIZE) {
                                /* full..move to next entry */
                                sg_kunmap_atomic(bounce_addr);
+                               bounce_addr = 0;
                                j++;
+                       }
 
-                               /* if we need to use another bounce buffer */
-                               if (srclen || i != orig_sgl_count - 1)
-                                       bounce_addr = sg_kmap_atomic(bounce_sgl,j);
+                       /* if we need to use another bounce buffer */
+                       if (srclen && bounce_addr == 0)
+                               bounce_addr = sg_kmap_atomic(bounce_sgl, j);
 
-                       } else if (srclen == 0 && i == orig_sgl_count - 1) {
-                               /* unmap the last bounce that is < PAGE_SIZE */
-                               sg_kunmap_atomic(bounce_addr);
-                       }
                }
 
                sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
        }
 
+       if (bounce_addr)
+               sg_kunmap_atomic(bounce_addr);
+
        local_irq_restore(flags);
 
        return total_copied;
index 911e9e0711d2a040116e7e1f1bd6514a6fe4ad53..a08f923b992532618e7917125451f5c0304cff83 100644 (file)
@@ -243,7 +243,10 @@ static int spidev_message(struct spidev_data *spidev,
                k_tmp->len = u_tmp->len;
 
                total += k_tmp->len;
-               if (total > bufsiz) {
+               /* Check total length of transfers.  Also check each
+                * transfer length to avoid arithmetic overflow.
+                */
+               if (total > bufsiz || k_tmp->len > bufsiz) {
                        status = -EMSGSIZE;
                        goto done;
                }
index aefe820a8005585934f9d80b2d62a69b44555b29..25c8bffdd248dfcdb692ace5fd7794e7ec6197d0 100644 (file)
@@ -72,10 +72,6 @@ source "drivers/staging/sep/Kconfig"
 
 source "drivers/staging/iio/Kconfig"
 
-source "drivers/staging/zsmalloc/Kconfig"
-
-source "drivers/staging/zram/Kconfig"
-
 source "drivers/staging/wlags49_h2/Kconfig"
 
 source "drivers/staging/wlags49_h25/Kconfig"
index 415772ea306dd160a9c19477b557ff16fd746fe6..f9d86a4b48e9772ad9687e90bb7b4da82957c748 100644 (file)
@@ -30,8 +30,6 @@ obj-$(CONFIG_VT6656)          += vt6656/
 obj-$(CONFIG_VME_BUS)          += vme/
 obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)              += iio/
-obj-$(CONFIG_ZRAM)             += zram/
-obj-$(CONFIG_ZSMALLOC)         += zsmalloc/
 obj-$(CONFIG_WLAGS49_H2)       += wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)      += wlags49_h25/
 obj-$(CONFIG_FB_SM7XX)         += sm7xxfb/
index b02cfe89eb0c9fca4e760a41e97e53085342c724..d2b069f0b4c60f3f5ff7456610db20a244c083e3 100755 (executable)
@@ -605,7 +605,8 @@ static void fiq_debugger_help(struct fiq_debugger_state *state)
                                " pc            PC status\n"
                                " regs          Register dump\n"
                                " allregs       Extended Register dump\n"
-                               " bt            Stack trace\n"
+                               " bt            Stack trace\n");
+       fiq_debugger_printf(&state->output,
                                " reboot [<c>]  Reboot with command <c>\n"
                                " reset [<c>]   Hard reset with command <c>\n"
                                " irqs          Interupt status\n"
index c54df3948e20206d4b0cc8f9ed8b68253daf4acc..4d0a87b93b96b7e6b66ee40f2d24b2547e90f705 100644 (file)
@@ -275,11 +275,11 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
  * LCD types
  */
 #define LCD_TYPE_NONE          0
-#define LCD_TYPE_OLD           1
-#define LCD_TYPE_KS0074                2
-#define LCD_TYPE_HANTRONIX     3
-#define LCD_TYPE_NEXCOM                4
-#define LCD_TYPE_CUSTOM                5
+#define LCD_TYPE_CUSTOM                1
+#define LCD_TYPE_OLD           2
+#define LCD_TYPE_KS0074                3
+#define LCD_TYPE_HANTRONIX     4
+#define LCD_TYPE_NEXCOM                5
 
 /*
  * keypad types
@@ -457,8 +457,7 @@ MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
 static int lcd_type = -1;
 module_param(lcd_type, int, 0000);
 MODULE_PARM_DESC(lcd_type,
-                "LCD type: 0=none, 1=old //, 2=serial ks0074, "
-                "3=hantronix //, 4=nexcom //, 5=compiled-in");
+               "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom");
 
 static int lcd_proto = -1;
 module_param(lcd_proto, int, 0000);
diff --git a/drivers/staging/zram/Kconfig b/drivers/staging/zram/Kconfig
deleted file mode 100644 (file)
index 983314c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-config ZRAM
-       tristate "Compressed RAM block device support"
-       depends on BLOCK && SYSFS && ZSMALLOC
-       select LZO_COMPRESS
-       select LZO_DECOMPRESS
-       default n
-       help
-         Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
-         Pages written to these disks are compressed and stored in memory
-         itself. These disks allow very fast I/O and compression provides
-         good amounts of memory savings.
-
-         It has several use cases, for example: /tmp storage, use as swap
-         disks and maybe many more.
-
-         See zram.txt for more information.
-         Project home: <https://compcache.googlecode.com/>
-
-config ZRAM_DEBUG
-       bool "Compressed RAM block device debug support"
-       depends on ZRAM
-       default n
-       help
-         This option adds additional debugging code to the compressed
-         RAM block device driver.
diff --git a/drivers/staging/zram/Makefile b/drivers/staging/zram/Makefile
deleted file mode 100644 (file)
index 7f4a301..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-zram-y :=      zram_drv.o zram_sysfs.o
-
-obj-$(CONFIG_ZRAM)     +=      zram.o
diff --git a/drivers/staging/zram/zram.txt b/drivers/staging/zram/zram.txt
deleted file mode 100644 (file)
index 765d790..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-zram: Compressed RAM based block devices
-----------------------------------------
-
-Project home: http://compcache.googlecode.com/
-
-* Introduction
-
-The zram module creates RAM based block devices named /dev/zram<id>
-(<id> = 0, 1, ...). Pages written to these disks are compressed and stored
-in memory itself. These disks allow very fast I/O and compression provides
-good amounts of memory savings. Some of the usecases include /tmp storage,
-use as swap disks, various caches under /var and maybe many more :)
-
-Statistics for individual zram devices are exported through sysfs nodes at
-/sys/block/zram<id>/
-
-* Usage
-
-Following shows a typical sequence of steps for using zram.
-
-1) Load Module:
-       modprobe zram num_devices=4
-       This creates 4 devices: /dev/zram{0,1,2,3}
-       (num_devices parameter is optional. Default: 1)
-
-2) Set Disksize
-        Set disk size by writing the value to sysfs node 'disksize'.
-        The value can be either in bytes or you can use mem suffixes.
-        Examples:
-            # Initialize /dev/zram0 with 50MB disksize
-            echo $((50*1024*1024)) > /sys/block/zram0/disksize
-
-            # Using mem suffixes
-            echo 256K > /sys/block/zram0/disksize
-            echo 512M > /sys/block/zram0/disksize
-            echo 1G > /sys/block/zram0/disksize
-
-3) Activate:
-       mkswap /dev/zram0
-       swapon /dev/zram0
-
-       mkfs.ext4 /dev/zram1
-       mount /dev/zram1 /tmp
-
-4) Stats:
-       Per-device statistics are exported as various nodes under
-       /sys/block/zram<id>/
-               disksize
-               num_reads
-               num_writes
-               invalid_io
-               notify_free
-               discard
-               zero_pages
-               orig_data_size
-               compr_data_size
-               mem_used_total
-
-5) Deactivate:
-       swapoff /dev/zram0
-       umount /dev/zram1
-
-6) Reset:
-       Write any positive value to 'reset' sysfs node
-       echo 1 > /sys/block/zram0/reset
-       echo 1 > /sys/block/zram1/reset
-
-       This frees all the memory allocated for the given device and
-       resets the disksize to zero. You must set the disksize again
-       before reusing the device.
-
-Please report any problems at:
- - Mailing list: linux-mm-cc at laptop dot org
- - Issue tracker: http://code.google.com/p/compcache/issues/list
-
-Nitin Gupta
-ngupta@vflare.org
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
deleted file mode 100644 (file)
index a333d44..0000000
+++ /dev/null
@@ -1,760 +0,0 @@
-/*
- * Compressed RAM block device
- *
- * Copyright (C) 2008, 2009, 2010  Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- *
- * Project home: http://compcache.googlecode.com
- */
-
-#define KMSG_COMPONENT "zram"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
-#ifdef CONFIG_ZRAM_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bio.h>
-#include <linux/bitops.h>
-#include <linux/blkdev.h>
-#include <linux/buffer_head.h>
-#include <linux/device.h>
-#include <linux/genhd.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/lzo.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-
-#include "zram_drv.h"
-
-/* Globals */
-static int zram_major;
-struct zram *zram_devices;
-
-/* Module params (documentation at end) */
-static unsigned int num_devices = 1;
-
-static void zram_stat64_add(struct zram *zram, u64 *v, u64 inc)
-{
-       spin_lock(&zram->stat64_lock);
-       *v = *v + inc;
-       spin_unlock(&zram->stat64_lock);
-}
-
-static void zram_stat64_sub(struct zram *zram, u64 *v, u64 dec)
-{
-       spin_lock(&zram->stat64_lock);
-       *v = *v - dec;
-       spin_unlock(&zram->stat64_lock);
-}
-
-static void zram_stat64_inc(struct zram *zram, u64 *v)
-{
-       zram_stat64_add(zram, v, 1);
-}
-
-static int zram_test_flag(struct zram_meta *meta, u32 index,
-                       enum zram_pageflags flag)
-{
-       return meta->table[index].flags & BIT(flag);
-}
-
-static void zram_set_flag(struct zram_meta *meta, u32 index,
-                       enum zram_pageflags flag)
-{
-       meta->table[index].flags |= BIT(flag);
-}
-
-static void zram_clear_flag(struct zram_meta *meta, u32 index,
-                       enum zram_pageflags flag)
-{
-       meta->table[index].flags &= ~BIT(flag);
-}
-
-static int page_zero_filled(void *ptr)
-{
-       unsigned int pos;
-       unsigned long *page;
-
-       page = (unsigned long *)ptr;
-
-       for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) {
-               if (page[pos])
-                       return 0;
-       }
-
-       return 1;
-}
-
-static void zram_free_page(struct zram *zram, size_t index)
-{
-       struct zram_meta *meta = zram->meta;
-       unsigned long handle = meta->table[index].handle;
-       u16 size = meta->table[index].size;
-
-       if (unlikely(!handle)) {
-               /*
-                * No memory is allocated for zero filled pages.
-                * Simply clear zero page flag.
-                */
-               if (zram_test_flag(meta, index, ZRAM_ZERO)) {
-                       zram_clear_flag(meta, index, ZRAM_ZERO);
-                       zram->stats.pages_zero--;
-               }
-               return;
-       }
-
-       if (unlikely(size > max_zpage_size))
-               zram->stats.bad_compress--;
-
-       zs_free(meta->mem_pool, handle);
-
-       if (size <= PAGE_SIZE / 2)
-               zram->stats.good_compress--;
-
-       zram_stat64_sub(zram, &zram->stats.compr_size,
-                       meta->table[index].size);
-       zram->stats.pages_stored--;
-
-       meta->table[index].handle = 0;
-       meta->table[index].size = 0;
-}
-
-static void handle_zero_page(struct bio_vec *bvec)
-{
-       struct page *page = bvec->bv_page;
-       void *user_mem;
-
-       user_mem = kmap_atomic(page);
-       memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
-       kunmap_atomic(user_mem);
-
-       flush_dcache_page(page);
-}
-
-static inline int is_partial_io(struct bio_vec *bvec)
-{
-       return bvec->bv_len != PAGE_SIZE;
-}
-
-static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
-{
-       int ret = LZO_E_OK;
-       size_t clen = PAGE_SIZE;
-       unsigned char *cmem;
-       struct zram_meta *meta = zram->meta;
-       unsigned long handle = meta->table[index].handle;
-
-       if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) {
-               memset(mem, 0, PAGE_SIZE);
-               return 0;
-       }
-
-       cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO);
-       if (meta->table[index].size == PAGE_SIZE)
-               memcpy(mem, cmem, PAGE_SIZE);
-       else
-               ret = lzo1x_decompress_safe(cmem, meta->table[index].size,
-                                               mem, &clen);
-       zs_unmap_object(meta->mem_pool, handle);
-
-       /* Should NEVER happen. Return bio error if it does. */
-       if (unlikely(ret != LZO_E_OK)) {
-               pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
-               zram_stat64_inc(zram, &zram->stats.failed_reads);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
-                         u32 index, int offset, struct bio *bio)
-{
-       int ret;
-       struct page *page;
-       unsigned char *user_mem, *uncmem = NULL;
-       struct zram_meta *meta = zram->meta;
-       page = bvec->bv_page;
-
-       if (unlikely(!meta->table[index].handle) ||
-                       zram_test_flag(meta, index, ZRAM_ZERO)) {
-               handle_zero_page(bvec);
-               return 0;
-       }
-
-       if (is_partial_io(bvec))
-               /* Use  a temporary buffer to decompress the page */
-               uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
-
-       user_mem = kmap_atomic(page);
-       if (!is_partial_io(bvec))
-               uncmem = user_mem;
-
-       if (!uncmem) {
-               pr_info("Unable to allocate temp memory\n");
-               ret = -ENOMEM;
-               goto out_cleanup;
-       }
-
-       ret = zram_decompress_page(zram, uncmem, index);
-       /* Should NEVER happen. Return bio error if it does. */
-       if (unlikely(ret != LZO_E_OK))
-               goto out_cleanup;
-
-       if (is_partial_io(bvec))
-               memcpy(user_mem + bvec->bv_offset, uncmem + offset,
-                               bvec->bv_len);
-
-       flush_dcache_page(page);
-       ret = 0;
-out_cleanup:
-       kunmap_atomic(user_mem);
-       if (is_partial_io(bvec))
-               kfree(uncmem);
-       return ret;
-}
-
-static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
-                          int offset)
-{
-       int ret = 0;
-       size_t clen;
-       unsigned long handle;
-       struct page *page;
-       unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
-       struct zram_meta *meta = zram->meta;
-
-       page = bvec->bv_page;
-       src = meta->compress_buffer;
-
-       if (is_partial_io(bvec)) {
-               /*
-                * This is a partial IO. We need to read the full page
-                * before to write the changes.
-                */
-               uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
-               if (!uncmem) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               ret = zram_decompress_page(zram, uncmem, index);
-               if (ret)
-                       goto out;
-       }
-
-       /*
-        * System overwrites unused sectors. Free memory associated
-        * with this sector now.
-        */
-       if (meta->table[index].handle ||
-           zram_test_flag(meta, index, ZRAM_ZERO))
-               zram_free_page(zram, index);
-
-       user_mem = kmap_atomic(page);
-
-       if (is_partial_io(bvec)) {
-               memcpy(uncmem + offset, user_mem + bvec->bv_offset,
-                      bvec->bv_len);
-               kunmap_atomic(user_mem);
-               user_mem = NULL;
-       } else {
-               uncmem = user_mem;
-       }
-
-       if (page_zero_filled(uncmem)) {
-               kunmap_atomic(user_mem);
-               zram->stats.pages_zero++;
-               zram_set_flag(meta, index, ZRAM_ZERO);
-               ret = 0;
-               goto out;
-       }
-
-       ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
-                              meta->compress_workmem);
-
-       if (!is_partial_io(bvec)) {
-               kunmap_atomic(user_mem);
-               user_mem = NULL;
-               uncmem = NULL;
-       }
-
-       if (unlikely(ret != LZO_E_OK)) {
-               pr_err("Compression failed! err=%d\n", ret);
-               goto out;
-       }
-
-       if (unlikely(clen > max_zpage_size)) {
-               zram->stats.bad_compress++;
-               clen = PAGE_SIZE;
-               src = NULL;
-               if (is_partial_io(bvec))
-                       src = uncmem;
-       }
-
-       handle = zs_malloc(meta->mem_pool, clen);
-       if (!handle) {
-               pr_info("Error allocating memory for compressed "
-                       "page: %u, size=%zu\n", index, clen);
-               ret = -ENOMEM;
-               goto out;
-       }
-       cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_WO);
-
-       if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
-               src = kmap_atomic(page);
-       memcpy(cmem, src, clen);
-       if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
-               kunmap_atomic(src);
-
-       zs_unmap_object(meta->mem_pool, handle);
-
-       meta->table[index].handle = handle;
-       meta->table[index].size = clen;
-
-       /* Update stats */
-       zram_stat64_add(zram, &zram->stats.compr_size, clen);
-       zram->stats.pages_stored++;
-       if (clen <= PAGE_SIZE / 2)
-               zram->stats.good_compress++;
-
-out:
-       if (is_partial_io(bvec))
-               kfree(uncmem);
-
-       if (ret)
-               zram_stat64_inc(zram, &zram->stats.failed_writes);
-       return ret;
-}
-
-static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
-                       int offset, struct bio *bio, int rw)
-{
-       int ret;
-
-       if (rw == READ) {
-               down_read(&zram->lock);
-               ret = zram_bvec_read(zram, bvec, index, offset, bio);
-               up_read(&zram->lock);
-       } else {
-               down_write(&zram->lock);
-               ret = zram_bvec_write(zram, bvec, index, offset);
-               up_write(&zram->lock);
-       }
-
-       return ret;
-}
-
-static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
-{
-       if (*offset + bvec->bv_len >= PAGE_SIZE)
-               (*index)++;
-       *offset = (*offset + bvec->bv_len) % PAGE_SIZE;
-}
-
-static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
-{
-       int i, offset;
-       u32 index;
-       struct bio_vec *bvec;
-
-       switch (rw) {
-       case READ:
-               zram_stat64_inc(zram, &zram->stats.num_reads);
-               break;
-       case WRITE:
-               zram_stat64_inc(zram, &zram->stats.num_writes);
-               break;
-       }
-
-       index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
-       offset = (bio->bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
-
-       bio_for_each_segment(bvec, bio, i) {
-               int max_transfer_size = PAGE_SIZE - offset;
-
-               if (bvec->bv_len > max_transfer_size) {
-                       /*
-                        * zram_bvec_rw() can only make operation on a single
-                        * zram page. Split the bio vector.
-                        */
-                       struct bio_vec bv;
-
-                       bv.bv_page = bvec->bv_page;
-                       bv.bv_len = max_transfer_size;
-                       bv.bv_offset = bvec->bv_offset;
-
-                       if (zram_bvec_rw(zram, &bv, index, offset, bio, rw) < 0)
-                               goto out;
-
-                       bv.bv_len = bvec->bv_len - max_transfer_size;
-                       bv.bv_offset += max_transfer_size;
-                       if (zram_bvec_rw(zram, &bv, index+1, 0, bio, rw) < 0)
-                               goto out;
-               } else
-                       if (zram_bvec_rw(zram, bvec, index, offset, bio, rw)
-                           < 0)
-                               goto out;
-
-               update_position(&index, &offset, bvec);
-       }
-
-       set_bit(BIO_UPTODATE, &bio->bi_flags);
-       bio_endio(bio, 0);
-       return;
-
-out:
-       bio_io_error(bio);
-}
-
-/*
- * Check if request is within bounds and aligned on zram logical blocks.
- */
-static inline int valid_io_request(struct zram *zram, struct bio *bio)
-{
-       u64 start, end, bound;
-
-       /* unaligned request */
-       if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
-               return 0;
-       if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
-               return 0;
-
-       start = bio->bi_sector;
-       end = start + (bio->bi_size >> SECTOR_SHIFT);
-       bound = zram->disksize >> SECTOR_SHIFT;
-       /* out of range range */
-       if (unlikely(start >= bound || end > bound || start > end))
-               return 0;
-
-       /* I/O request is valid */
-       return 1;
-}
-
-/*
- * Handler function for all zram I/O requests.
- */
-static void zram_make_request(struct request_queue *queue, struct bio *bio)
-{
-       struct zram *zram = queue->queuedata;
-
-       down_read(&zram->init_lock);
-       if (unlikely(!zram->init_done))
-               goto error;
-
-       if (!valid_io_request(zram, bio)) {
-               zram_stat64_inc(zram, &zram->stats.invalid_io);
-               goto error;
-       }
-
-       __zram_make_request(zram, bio, bio_data_dir(bio));
-       up_read(&zram->init_lock);
-
-       return;
-
-error:
-       up_read(&zram->init_lock);
-       bio_io_error(bio);
-}
-
-static void __zram_reset_device(struct zram *zram)
-{
-       size_t index;
-       struct zram_meta *meta;
-
-       if (!zram->init_done)
-               return;
-
-       meta = zram->meta;
-       zram->init_done = 0;
-
-       /* Free all pages that are still in this zram device */
-       for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) {
-               unsigned long handle = meta->table[index].handle;
-               if (!handle)
-                       continue;
-
-               zs_free(meta->mem_pool, handle);
-       }
-
-       zram_meta_free(zram->meta);
-       zram->meta = NULL;
-       /* Reset stats */
-       memset(&zram->stats, 0, sizeof(zram->stats));
-
-       zram->disksize = 0;
-       set_capacity(zram->disk, 0);
-}
-
-void zram_reset_device(struct zram *zram)
-{
-       down_write(&zram->init_lock);
-       __zram_reset_device(zram);
-       up_write(&zram->init_lock);
-}
-
-void zram_meta_free(struct zram_meta *meta)
-{
-       zs_destroy_pool(meta->mem_pool);
-       kfree(meta->compress_workmem);
-       free_pages((unsigned long)meta->compress_buffer, 1);
-       vfree(meta->table);
-       kfree(meta);
-}
-
-struct zram_meta *zram_meta_alloc(u64 disksize)
-{
-       size_t num_pages;
-       struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
-       if (!meta)
-               goto out;
-
-       meta->compress_workmem = kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
-       if (!meta->compress_workmem)
-               goto free_meta;
-
-       meta->compress_buffer =
-               (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
-       if (!meta->compress_buffer) {
-               pr_err("Error allocating compressor buffer space\n");
-               goto free_workmem;
-       }
-
-       num_pages = disksize >> PAGE_SHIFT;
-       meta->table = vzalloc(num_pages * sizeof(*meta->table));
-       if (!meta->table) {
-               pr_err("Error allocating zram address table\n");
-               goto free_buffer;
-       }
-
-       meta->mem_pool = zs_create_pool(GFP_NOIO | __GFP_HIGHMEM);
-       if (!meta->mem_pool) {
-               pr_err("Error creating memory pool\n");
-               goto free_table;
-       }
-
-       return meta;
-
-free_table:
-       vfree(meta->table);
-free_buffer:
-       free_pages((unsigned long)meta->compress_buffer, 1);
-free_workmem:
-       kfree(meta->compress_workmem);
-free_meta:
-       kfree(meta);
-       meta = NULL;
-out:
-       return meta;
-}
-
-void zram_init_device(struct zram *zram, struct zram_meta *meta)
-{
-       if (zram->disksize > 2 * (totalram_pages << PAGE_SHIFT)) {
-               pr_info(
-               "There is little point creating a zram of greater than "
-               "twice the size of memory since we expect a 2:1 compression "
-               "ratio. Note that zram uses about 0.1%% of the size of "
-               "the disk when not in use so a huge zram is "
-               "wasteful.\n"
-               "\tMemory Size: %lu kB\n"
-               "\tSize you selected: %llu kB\n"
-               "Continuing anyway ...\n",
-               (totalram_pages << PAGE_SHIFT) >> 10, zram->disksize >> 10
-               );
-       }
-
-       /* zram devices sort of resembles non-rotational disks */
-       queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue);
-
-       zram->meta = meta;
-       zram->init_done = 1;
-
-       pr_debug("Initialization done!\n");
-}
-
-static void zram_slot_free_notify(struct block_device *bdev,
-                               unsigned long index)
-{
-       struct zram *zram;
-
-       zram = bdev->bd_disk->private_data;
-       down_write(&zram->lock);
-       zram_free_page(zram, index);
-       up_write(&zram->lock);
-       zram_stat64_inc(zram, &zram->stats.notify_free);
-}
-
-static const struct block_device_operations zram_devops = {
-       .swap_slot_free_notify = zram_slot_free_notify,
-       .owner = THIS_MODULE
-};
-
-static int create_device(struct zram *zram, int device_id)
-{
-       int ret = -ENOMEM;
-
-       init_rwsem(&zram->lock);
-       init_rwsem(&zram->init_lock);
-       spin_lock_init(&zram->stat64_lock);
-
-       zram->queue = blk_alloc_queue(GFP_KERNEL);
-       if (!zram->queue) {
-               pr_err("Error allocating disk queue for device %d\n",
-                       device_id);
-               goto out;
-       }
-
-       blk_queue_make_request(zram->queue, zram_make_request);
-       zram->queue->queuedata = zram;
-
-        /* gendisk structure */
-       zram->disk = alloc_disk(1);
-       if (!zram->disk) {
-               pr_warn("Error allocating disk structure for device %d\n",
-                       device_id);
-               goto out_free_queue;
-       }
-
-       zram->disk->major = zram_major;
-       zram->disk->first_minor = device_id;
-       zram->disk->fops = &zram_devops;
-       zram->disk->queue = zram->queue;
-       zram->disk->private_data = zram;
-       snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
-
-       /* Actual capacity set using syfs (/sys/block/zram<id>/disksize */
-       set_capacity(zram->disk, 0);
-
-       /*
-        * To ensure that we always get PAGE_SIZE aligned
-        * and n*PAGE_SIZED sized I/O requests.
-        */
-       blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE);
-       blk_queue_logical_block_size(zram->disk->queue,
-                                       ZRAM_LOGICAL_BLOCK_SIZE);
-       blk_queue_io_min(zram->disk->queue, PAGE_SIZE);
-       blk_queue_io_opt(zram->disk->queue, PAGE_SIZE);
-
-       add_disk(zram->disk);
-
-       ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
-                               &zram_disk_attr_group);
-       if (ret < 0) {
-               pr_warn("Error creating sysfs group");
-               goto out_free_disk;
-       }
-
-       zram->init_done = 0;
-       return 0;
-
-out_free_disk:
-       del_gendisk(zram->disk);
-       put_disk(zram->disk);
-out_free_queue:
-       blk_cleanup_queue(zram->queue);
-out:
-       return ret;
-}
-
-static void destroy_device(struct zram *zram)
-{
-       sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
-                       &zram_disk_attr_group);
-
-       if (zram->disk) {
-               del_gendisk(zram->disk);
-               put_disk(zram->disk);
-       }
-
-       if (zram->queue)
-               blk_cleanup_queue(zram->queue);
-}
-
-unsigned int zram_get_num_devices(void)
-{
-       return num_devices;
-}
-
-static int __init zram_init(void)
-{
-       int ret, dev_id;
-
-       if (num_devices > max_num_devices) {
-               pr_warn("Invalid value for num_devices: %u\n",
-                               num_devices);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       zram_major = register_blkdev(0, "zram");
-       if (zram_major <= 0) {
-               pr_warn("Unable to get major number\n");
-               ret = -EBUSY;
-               goto out;
-       }
-
-       /* Allocate the device array and initialize each one */
-       zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
-       if (!zram_devices) {
-               ret = -ENOMEM;
-               goto unregister;
-       }
-
-       for (dev_id = 0; dev_id < num_devices; dev_id++) {
-               ret = create_device(&zram_devices[dev_id], dev_id);
-               if (ret)
-                       goto free_devices;
-       }
-
-       pr_info("Created %u device(s) ...\n", num_devices);
-
-       return 0;
-
-free_devices:
-       while (dev_id)
-               destroy_device(&zram_devices[--dev_id]);
-       kfree(zram_devices);
-unregister:
-       unregister_blkdev(zram_major, "zram");
-out:
-       return ret;
-}
-
-static void __exit zram_exit(void)
-{
-       int i;
-       struct zram *zram;
-
-       for (i = 0; i < num_devices; i++) {
-               zram = &zram_devices[i];
-
-               get_disk(zram->disk);
-               destroy_device(zram);
-               zram_reset_device(zram);
-               put_disk(zram->disk);
-       }
-
-       unregister_blkdev(zram_major, "zram");
-
-       kfree(zram_devices);
-       pr_debug("Cleanup done!\n");
-}
-
-module_param(num_devices, uint, 0);
-MODULE_PARM_DESC(num_devices, "Number of zram devices");
-
-module_init(zram_init);
-module_exit(zram_exit);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
-MODULE_DESCRIPTION("Compressed RAM Block Device");
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
deleted file mode 100644 (file)
index d542eee..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Compressed RAM block device
- *
- * Copyright (C) 2008, 2009, 2010  Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- *
- * Project home: http://compcache.googlecode.com
- */
-
-#ifndef _ZRAM_DRV_H_
-#define _ZRAM_DRV_H_
-
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-
-#include "../zsmalloc/zsmalloc.h"
-
-/*
- * Some arbitrary value. This is just to catch
- * invalid value for num_devices module parameter.
- */
-static const unsigned max_num_devices = 32;
-
-/*-- Configurable parameters */
-
-/*
- * Pages that compress to size greater than this are stored
- * uncompressed in memory.
- */
-static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
-
-/*
- * NOTE: max_zpage_size must be less than or equal to:
- *   ZS_MAX_ALLOC_SIZE. Otherwise, zs_malloc() would
- * always return failure.
- */
-
-/*-- End of configurable params */
-
-#define SECTOR_SHIFT           9
-#define SECTOR_SIZE            (1 << SECTOR_SHIFT)
-#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
-#define SECTORS_PER_PAGE       (1 << SECTORS_PER_PAGE_SHIFT)
-#define ZRAM_LOGICAL_BLOCK_SHIFT 12
-#define ZRAM_LOGICAL_BLOCK_SIZE        (1 << ZRAM_LOGICAL_BLOCK_SHIFT)
-#define ZRAM_SECTOR_PER_LOGICAL_BLOCK  \
-       (1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
-
-/* Flags for zram pages (table[page_no].flags) */
-enum zram_pageflags {
-       /* Page consists entirely of zeros */
-       ZRAM_ZERO,
-
-       __NR_ZRAM_PAGEFLAGS,
-};
-
-/*-- Data structures */
-
-/* Allocated for each disk page */
-struct table {
-       unsigned long handle;
-       u16 size;       /* object size (excluding header) */
-       u8 count;       /* object ref count (not yet used) */
-       u8 flags;
-} __aligned(4);
-
-struct zram_stats {
-       u64 compr_size;         /* compressed size of pages stored */
-       u64 num_reads;          /* failed + successful */
-       u64 num_writes;         /* --do-- */
-       u64 failed_reads;       /* should NEVER! happen */
-       u64 failed_writes;      /* can happen when memory is too low */
-       u64 invalid_io;         /* non-page-aligned I/O requests */
-       u64 notify_free;        /* no. of swap slot free notifications */
-       u32 pages_zero;         /* no. of zero filled pages */
-       u32 pages_stored;       /* no. of pages currently stored */
-       u32 good_compress;      /* % of pages with compression ratio<=50% */
-       u32 bad_compress;       /* % of pages with compression ratio>=75% */
-};
-
-struct zram_meta {
-       void *compress_workmem;
-       void *compress_buffer;
-       struct table *table;
-       struct zs_pool *mem_pool;
-};
-
-struct zram {
-       struct zram_meta *meta;
-       spinlock_t stat64_lock; /* protect 64-bit stats */
-       struct rw_semaphore lock; /* protect compression buffers, table,
-                                  * 32bit stat counters against concurrent
-                                  * notifications, reads and writes */
-       struct request_queue *queue;
-       struct gendisk *disk;
-       int init_done;
-       /* Prevent concurrent execution of device init, reset and R/W request */
-       struct rw_semaphore init_lock;
-       /*
-        * This is the limit on amount of *uncompressed* worth of data
-        * we can store in a disk.
-        */
-       u64 disksize;   /* bytes */
-
-       struct zram_stats stats;
-};
-
-extern struct zram *zram_devices;
-unsigned int zram_get_num_devices(void);
-#ifdef CONFIG_SYSFS
-extern struct attribute_group zram_disk_attr_group;
-#endif
-
-extern void zram_reset_device(struct zram *zram);
-extern struct zram_meta *zram_meta_alloc(u64 disksize);
-extern void zram_meta_free(struct zram_meta *meta);
-extern void zram_init_device(struct zram *zram, struct zram_meta *meta);
-
-#endif
diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c
deleted file mode 100644 (file)
index dc76a3d..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Compressed RAM block device
- *
- * Copyright (C) 2008, 2009, 2010  Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the licence that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- *
- * Project home: http://compcache.googlecode.com/
- */
-
-#include <linux/device.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-
-#include "zram_drv.h"
-
-static u64 zram_stat64_read(struct zram *zram, u64 *v)
-{
-       u64 val;
-
-       spin_lock(&zram->stat64_lock);
-       val = *v;
-       spin_unlock(&zram->stat64_lock);
-
-       return val;
-}
-
-static struct zram *dev_to_zram(struct device *dev)
-{
-       int i;
-       struct zram *zram = NULL;
-
-       for (i = 0; i < zram_get_num_devices(); i++) {
-               zram = &zram_devices[i];
-               if (disk_to_dev(zram->disk) == dev)
-                       break;
-       }
-
-       return zram;
-}
-
-static ssize_t disksize_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%llu\n", zram->disksize);
-}
-
-static ssize_t disksize_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t len)
-{
-       u64 disksize;
-       struct zram_meta *meta;
-       struct zram *zram = dev_to_zram(dev);
-
-       disksize = memparse(buf, NULL);
-       if (!disksize)
-               return -EINVAL;
-
-       disksize = PAGE_ALIGN(disksize);
-       meta = zram_meta_alloc(disksize);
-       down_write(&zram->init_lock);
-       if (zram->init_done) {
-               up_write(&zram->init_lock);
-               zram_meta_free(meta);
-               pr_info("Cannot change disksize for initialized device\n");
-               return -EBUSY;
-       }
-
-       zram->disksize = disksize;
-       set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
-       zram_init_device(zram, meta);
-       up_write(&zram->init_lock);
-
-       return len;
-}
-
-static ssize_t initstate_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%u\n", zram->init_done);
-}
-
-static ssize_t reset_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t len)
-{
-       int ret;
-       unsigned short do_reset;
-       struct zram *zram;
-       struct block_device *bdev;
-
-       zram = dev_to_zram(dev);
-       bdev = bdget_disk(zram->disk, 0);
-
-       /* Do not reset an active device! */
-       if (bdev->bd_holders)
-               return -EBUSY;
-
-       ret = kstrtou16(buf, 10, &do_reset);
-       if (ret)
-               return ret;
-
-       if (!do_reset)
-               return -EINVAL;
-
-       /* Make sure all pending I/O is finished */
-       if (bdev)
-               fsync_bdev(bdev);
-
-       zram_reset_device(zram);
-       return len;
-}
-
-static ssize_t num_reads_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%llu\n",
-               zram_stat64_read(zram, &zram->stats.num_reads));
-}
-
-static ssize_t num_writes_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%llu\n",
-               zram_stat64_read(zram, &zram->stats.num_writes));
-}
-
-static ssize_t invalid_io_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%llu\n",
-               zram_stat64_read(zram, &zram->stats.invalid_io));
-}
-
-static ssize_t notify_free_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%llu\n",
-               zram_stat64_read(zram, &zram->stats.notify_free));
-}
-
-static ssize_t zero_pages_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%u\n", zram->stats.pages_zero);
-}
-
-static ssize_t orig_data_size_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%llu\n",
-               (u64)(zram->stats.pages_stored) << PAGE_SHIFT);
-}
-
-static ssize_t compr_data_size_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct zram *zram = dev_to_zram(dev);
-
-       return sprintf(buf, "%llu\n",
-               zram_stat64_read(zram, &zram->stats.compr_size));
-}
-
-static ssize_t mem_used_total_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       u64 val = 0;
-       struct zram *zram = dev_to_zram(dev);
-       struct zram_meta *meta = zram->meta;
-
-       down_read(&zram->init_lock);
-       if (zram->init_done)
-               val = zs_get_total_size_bytes(meta->mem_pool);
-       up_read(&zram->init_lock);
-
-       return sprintf(buf, "%llu\n", val);
-}
-
-static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR,
-               disksize_show, disksize_store);
-static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
-static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
-static DEVICE_ATTR(num_reads, S_IRUGO, num_reads_show, NULL);
-static DEVICE_ATTR(num_writes, S_IRUGO, num_writes_show, NULL);
-static DEVICE_ATTR(invalid_io, S_IRUGO, invalid_io_show, NULL);
-static DEVICE_ATTR(notify_free, S_IRUGO, notify_free_show, NULL);
-static DEVICE_ATTR(zero_pages, S_IRUGO, zero_pages_show, NULL);
-static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
-static DEVICE_ATTR(compr_data_size, S_IRUGO, compr_data_size_show, NULL);
-static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
-
-static struct attribute *zram_disk_attrs[] = {
-       &dev_attr_disksize.attr,
-       &dev_attr_initstate.attr,
-       &dev_attr_reset.attr,
-       &dev_attr_num_reads.attr,
-       &dev_attr_num_writes.attr,
-       &dev_attr_invalid_io.attr,
-       &dev_attr_notify_free.attr,
-       &dev_attr_zero_pages.attr,
-       &dev_attr_orig_data_size.attr,
-       &dev_attr_compr_data_size.attr,
-       &dev_attr_mem_used_total.attr,
-       NULL,
-};
-
-struct attribute_group zram_disk_attr_group = {
-       .attrs = zram_disk_attrs,
-};
diff --git a/drivers/staging/zsmalloc/Makefile b/drivers/staging/zsmalloc/Makefile
deleted file mode 100644 (file)
index b134848..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-zsmalloc-y             := zsmalloc-main.o
-
-obj-$(CONFIG_ZSMALLOC) += zsmalloc.o
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c
deleted file mode 100644 (file)
index 288f582..0000000
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*
- * zsmalloc memory allocator
- *
- * Copyright (C) 2011  Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the license that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- */
-
-
-/*
- * This allocator is designed for use with zcache and zram. Thus, the
- * allocator is supposed to work well under low memory conditions. In
- * particular, it never attempts higher order page allocation which is
- * very likely to fail under memory pressure. On the other hand, if we
- * just use single (0-order) pages, it would suffer from very high
- * fragmentation -- any object of size PAGE_SIZE/2 or larger would occupy
- * an entire page. This was one of the major issues with its predecessor
- * (xvmalloc).
- *
- * To overcome these issues, zsmalloc allocates a bunch of 0-order pages
- * and links them together using various 'struct page' fields. These linked
- * pages act as a single higher-order page i.e. an object can span 0-order
- * page boundaries. The code refers to these linked pages as a single entity
- * called zspage.
- *
- * Following is how we use various fields and flags of underlying
- * struct page(s) to form a zspage.
- *
- * Usage of struct page fields:
- *     page->first_page: points to the first component (0-order) page
- *     page->index (union with page->freelist): offset of the first object
- *             starting in this page. For the first page, this is
- *             always 0, so we use this field (aka freelist) to point
- *             to the first free object in zspage.
- *     page->lru: links together all component pages (except the first page)
- *             of a zspage
- *
- *     For _first_ page only:
- *
- *     page->private (union with page->first_page): refers to the
- *             component page after the first page
- *     page->freelist: points to the first free object in zspage.
- *             Free objects are linked together using in-place
- *             metadata.
- *     page->objects: maximum number of objects we can store in this
- *             zspage (class->zspage_order * PAGE_SIZE / class->size)
- *     page->lru: links together first pages of various zspages.
- *             Basically forming list of zspages in a fullness group.
- *     page->mapping: class index and fullness group of the zspage
- *
- * Usage of struct page flags:
- *     PG_private: identifies the first component page
- *     PG_private2: identifies the last component page
- *
- */
-
-#ifdef CONFIG_ZSMALLOC_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-#include <linux/errno.h>
-#include <linux/highmem.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <asm/tlbflush.h>
-#include <asm/pgtable.h>
-#include <linux/cpumask.h>
-#include <linux/cpu.h>
-#include <linux/vmalloc.h>
-#include <linux/hardirq.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include "zsmalloc.h"
-
-/*
- * This must be power of 2 and greater than of equal to sizeof(link_free).
- * These two conditions ensure that any 'struct link_free' itself doesn't
- * span more than 1 page which avoids complex case of mapping 2 pages simply
- * to restore link_free pointer values.
- */
-#define ZS_ALIGN               8
-
-/*
- * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single)
- * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N.
- */
-#define ZS_MAX_ZSPAGE_ORDER 2
-#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
-
-/*
- * Object location (<PFN>, <obj_idx>) is encoded as
- * as single (void *) handle value.
- *
- * Note that object index <obj_idx> is relative to system
- * page <PFN> it is stored in, so for each sub-page belonging
- * to a zspage, obj_idx starts with 0.
- *
- * This is made more complicated by various memory models and PAE.
- */
-
-#ifndef MAX_PHYSMEM_BITS
-#ifdef CONFIG_HIGHMEM64G
-#define MAX_PHYSMEM_BITS 36
-#else /* !CONFIG_HIGHMEM64G */
-/*
- * If this definition of MAX_PHYSMEM_BITS is used, OBJ_INDEX_BITS will just
- * be PAGE_SHIFT
- */
-#define MAX_PHYSMEM_BITS BITS_PER_LONG
-#endif
-#endif
-#define _PFN_BITS              (MAX_PHYSMEM_BITS - PAGE_SHIFT)
-#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS)
-#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1)
-
-#define MAX(a, b) ((a) >= (b) ? (a) : (b))
-/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
-#define ZS_MIN_ALLOC_SIZE \
-       MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
-#define ZS_MAX_ALLOC_SIZE      PAGE_SIZE
-
-/*
- * On systems with 4K page size, this gives 254 size classes! There is a
- * trader-off here:
- *  - Large number of size classes is potentially wasteful as free page are
- *    spread across these classes
- *  - Small number of size classes causes large internal fragmentation
- *  - Probably its better to use specific size classes (empirically
- *    determined). NOTE: all those class sizes must be set as multiple of
- *    ZS_ALIGN to make sure link_free itself never has to span 2 pages.
- *
- *  ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN
- *  (reason above)
- */
-#define ZS_SIZE_CLASS_DELTA    (PAGE_SIZE >> 8)
-#define ZS_SIZE_CLASSES                ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \
-                                       ZS_SIZE_CLASS_DELTA + 1)
-
-/*
- * We do not maintain any list for completely empty or full pages
- */
-enum fullness_group {
-       ZS_ALMOST_FULL,
-       ZS_ALMOST_EMPTY,
-       _ZS_NR_FULLNESS_GROUPS,
-
-       ZS_EMPTY,
-       ZS_FULL
-};
-
-/*
- * We assign a page to ZS_ALMOST_EMPTY fullness group when:
- *     n <= N / f, where
- * n = number of allocated objects
- * N = total number of objects zspage can store
- * f = 1/fullness_threshold_frac
- *
- * Similarly, we assign zspage to:
- *     ZS_ALMOST_FULL  when n > N / f
- *     ZS_EMPTY        when n == 0
- *     ZS_FULL         when n == N
- *
- * (see: fix_fullness_group())
- */
-static const int fullness_threshold_frac = 4;
-
-struct size_class {
-       /*
-        * Size of objects stored in this class. Must be multiple
-        * of ZS_ALIGN.
-        */
-       int size;
-       unsigned int index;
-
-       /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */
-       int pages_per_zspage;
-
-       spinlock_t lock;
-
-       /* stats */
-       u64 pages_allocated;
-
-       struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS];
-};
-
-/*
- * Placed within free objects to form a singly linked list.
- * For every zspage, first_page->freelist gives head of this list.
- *
- * This must be power of 2 and less than or equal to ZS_ALIGN
- */
-struct link_free {
-       /* Handle of next free chunk (encodes <PFN, obj_idx>) */
-       void *next;
-};
-
-struct zs_pool {
-       struct size_class size_class[ZS_SIZE_CLASSES];
-
-       gfp_t flags;    /* allocation flags used when growing pool */
-};
-
-/*
- * A zspage's class index and fullness group
- * are encoded in its (first)page->mapping
- */
-#define CLASS_IDX_BITS 28
-#define FULLNESS_BITS  4
-#define CLASS_IDX_MASK ((1 << CLASS_IDX_BITS) - 1)
-#define FULLNESS_MASK  ((1 << FULLNESS_BITS) - 1)
-
-/*
- * By default, zsmalloc uses a copy-based object mapping method to access
- * allocations that span two pages. However, if a particular architecture
- * performs VM mapping faster than copying, then it should be added here
- * so that USE_PGTABLE_MAPPING is defined. This causes zsmalloc to use
- * page table mapping rather than copying for object mapping.
-*/
-#if defined(CONFIG_ARM) && !defined(MODULE)
-#define USE_PGTABLE_MAPPING
-#endif
-
-struct mapping_area {
-#ifdef USE_PGTABLE_MAPPING
-       struct vm_struct *vm; /* vm area for mapping object that span pages */
-#else
-       char *vm_buf; /* copy buffer for objects that span pages */
-#endif
-       char *vm_addr; /* address of kmap_atomic()'ed pages */
-       enum zs_mapmode vm_mm; /* mapping mode */
-};
-
-
-/* per-cpu VM mapping areas for zspage accesses that cross page boundaries */
-static DEFINE_PER_CPU(struct mapping_area, zs_map_area);
-
-static int is_first_page(struct page *page)
-{
-       return PagePrivate(page);
-}
-
-static int is_last_page(struct page *page)
-{
-       return PagePrivate2(page);
-}
-
-static void get_zspage_mapping(struct page *page, unsigned int *class_idx,
-                               enum fullness_group *fullness)
-{
-       unsigned long m;
-       BUG_ON(!is_first_page(page));
-
-       m = (unsigned long)page->mapping;
-       *fullness = m & FULLNESS_MASK;
-       *class_idx = (m >> FULLNESS_BITS) & CLASS_IDX_MASK;
-}
-
-static void set_zspage_mapping(struct page *page, unsigned int class_idx,
-                               enum fullness_group fullness)
-{
-       unsigned long m;
-       BUG_ON(!is_first_page(page));
-
-       m = ((class_idx & CLASS_IDX_MASK) << FULLNESS_BITS) |
-                       (fullness & FULLNESS_MASK);
-       page->mapping = (struct address_space *)m;
-}
-
-static int get_size_class_index(int size)
-{
-       int idx = 0;
-
-       if (likely(size > ZS_MIN_ALLOC_SIZE))
-               idx = DIV_ROUND_UP(size - ZS_MIN_ALLOC_SIZE,
-                               ZS_SIZE_CLASS_DELTA);
-
-       return idx;
-}
-
-static enum fullness_group get_fullness_group(struct page *page)
-{
-       int inuse, max_objects;
-       enum fullness_group fg;
-       BUG_ON(!is_first_page(page));
-
-       inuse = page->inuse;
-       max_objects = page->objects;
-
-       if (inuse == 0)
-               fg = ZS_EMPTY;
-       else if (inuse == max_objects)
-               fg = ZS_FULL;
-       else if (inuse <= max_objects / fullness_threshold_frac)
-               fg = ZS_ALMOST_EMPTY;
-       else
-               fg = ZS_ALMOST_FULL;
-
-       return fg;
-}
-
-static void insert_zspage(struct page *page, struct size_class *class,
-                               enum fullness_group fullness)
-{
-       struct page **head;
-
-       BUG_ON(!is_first_page(page));
-
-       if (fullness >= _ZS_NR_FULLNESS_GROUPS)
-               return;
-
-       head = &class->fullness_list[fullness];
-       if (*head)
-               list_add_tail(&page->lru, &(*head)->lru);
-
-       *head = page;
-}
-
-static void remove_zspage(struct page *page, struct size_class *class,
-                               enum fullness_group fullness)
-{
-       struct page **head;
-
-       BUG_ON(!is_first_page(page));
-
-       if (fullness >= _ZS_NR_FULLNESS_GROUPS)
-               return;
-
-       head = &class->fullness_list[fullness];
-       BUG_ON(!*head);
-       if (list_empty(&(*head)->lru))
-               *head = NULL;
-       else if (*head == page)
-               *head = (struct page *)list_entry((*head)->lru.next,
-                                       struct page, lru);
-
-       list_del_init(&page->lru);
-}
-
-static enum fullness_group fix_fullness_group(struct zs_pool *pool,
-                                               struct page *page)
-{
-       int class_idx;
-       struct size_class *class;
-       enum fullness_group currfg, newfg;
-
-       BUG_ON(!is_first_page(page));
-
-       get_zspage_mapping(page, &class_idx, &currfg);
-       newfg = get_fullness_group(page);
-       if (newfg == currfg)
-               goto out;
-
-       class = &pool->size_class[class_idx];
-       remove_zspage(page, class, currfg);
-       insert_zspage(page, class, newfg);
-       set_zspage_mapping(page, class_idx, newfg);
-
-out:
-       return newfg;
-}
-
-/*
- * We have to decide on how many pages to link together
- * to form a zspage for each size class. This is important
- * to reduce wastage due to unusable space left at end of
- * each zspage which is given as:
- *     wastage = Zp - Zp % size_class
- * where Zp = zspage size = k * PAGE_SIZE where k = 1, 2, ...
- *
- * For example, for size class of 3/8 * PAGE_SIZE, we should
- * link together 3 PAGE_SIZE sized pages to form a zspage
- * since then we can perfectly fit in 8 such objects.
- */
-static int get_pages_per_zspage(int class_size)
-{
-       int i, max_usedpc = 0;
-       /* zspage order which gives maximum used size per KB */
-       int max_usedpc_order = 1;
-
-       for (i = 1; i <= ZS_MAX_PAGES_PER_ZSPAGE; i++) {
-               int zspage_size;
-               int waste, usedpc;
-
-               zspage_size = i * PAGE_SIZE;
-               waste = zspage_size % class_size;
-               usedpc = (zspage_size - waste) * 100 / zspage_size;
-
-               if (usedpc > max_usedpc) {
-                       max_usedpc = usedpc;
-                       max_usedpc_order = i;
-               }
-       }
-
-       return max_usedpc_order;
-}
-
-/*
- * A single 'zspage' is composed of many system pages which are
- * linked together using fields in struct page. This function finds
- * the first/head page, given any component page of a zspage.
- */
-static struct page *get_first_page(struct page *page)
-{
-       if (is_first_page(page))
-               return page;
-       else
-               return page->first_page;
-}
-
-static struct page *get_next_page(struct page *page)
-{
-       struct page *next;
-
-       if (is_last_page(page))
-               next = NULL;
-       else if (is_first_page(page))
-               next = (struct page *)page->private;
-       else
-               next = list_entry(page->lru.next, struct page, lru);
-
-       return next;
-}
-
-/*
- * Encode <page, obj_idx> as a single handle value.
- * On hardware platforms with physical memory starting at 0x0 the pfn
- * could be 0 so we ensure that the handle will never be 0 by adjusting the
- * encoded obj_idx value before encoding.
- */
-static void *obj_location_to_handle(struct page *page, unsigned long obj_idx)
-{
-       unsigned long handle;
-
-       if (!page) {
-               BUG_ON(obj_idx);
-               return NULL;
-       }
-
-       handle = page_to_pfn(page) << OBJ_INDEX_BITS;
-       handle |= ((obj_idx + 1) & OBJ_INDEX_MASK);
-
-       return (void *)handle;
-}
-
-/*
- * Decode <page, obj_idx> pair from the given object handle. We adjust the
- * decoded obj_idx back to its original value since it was adjusted in
- * obj_location_to_handle().
- */
-static void obj_handle_to_location(unsigned long handle, struct page **page,
-                               unsigned long *obj_idx)
-{
-       *page = pfn_to_page(handle >> OBJ_INDEX_BITS);
-       *obj_idx = (handle & OBJ_INDEX_MASK) - 1;
-}
-
-static unsigned long obj_idx_to_offset(struct page *page,
-                               unsigned long obj_idx, int class_size)
-{
-       unsigned long off = 0;
-
-       if (!is_first_page(page))
-               off = page->index;
-
-       return off + obj_idx * class_size;
-}
-
-static void reset_page(struct page *page)
-{
-       clear_bit(PG_private, &page->flags);
-       clear_bit(PG_private_2, &page->flags);
-       set_page_private(page, 0);
-       page->mapping = NULL;
-       page->freelist = NULL;
-       page_mapcount_reset(page);
-}
-
-static void free_zspage(struct page *first_page)
-{
-       struct page *nextp, *tmp, *head_extra;
-
-       BUG_ON(!is_first_page(first_page));
-       BUG_ON(first_page->inuse);
-
-       head_extra = (struct page *)page_private(first_page);
-
-       reset_page(first_page);
-       __free_page(first_page);
-
-       /* zspage with only 1 system page */
-       if (!head_extra)
-               return;
-
-       list_for_each_entry_safe(nextp, tmp, &head_extra->lru, lru) {
-               list_del(&nextp->lru);
-               reset_page(nextp);
-               __free_page(nextp);
-       }
-       reset_page(head_extra);
-       __free_page(head_extra);
-}
-
-/* Initialize a newly allocated zspage */
-static void init_zspage(struct page *first_page, struct size_class *class)
-{
-       unsigned long off = 0;
-       struct page *page = first_page;
-
-       BUG_ON(!is_first_page(first_page));
-       while (page) {
-               struct page *next_page;
-               struct link_free *link;
-               unsigned int i, objs_on_page;
-
-               /*
-                * page->index stores offset of first object starting
-                * in the page. For the first page, this is always 0,
-                * so we use first_page->index (aka ->freelist) to store
-                * head of corresponding zspage's freelist.
-                */
-               if (page != first_page)
-                       page->index = off;
-
-               link = (struct link_free *)kmap_atomic(page) +
-                                               off / sizeof(*link);
-               objs_on_page = (PAGE_SIZE - off) / class->size;
-
-               for (i = 1; i <= objs_on_page; i++) {
-                       off += class->size;
-                       if (off < PAGE_SIZE) {
-                               link->next = obj_location_to_handle(page, i);
-                               link += class->size / sizeof(*link);
-                       }
-               }
-
-               /*
-                * We now come to the last (full or partial) object on this
-                * page, which must point to the first object on the next
-                * page (if present)
-                */
-               next_page = get_next_page(page);
-               link->next = obj_location_to_handle(next_page, 0);
-               kunmap_atomic(link);
-               page = next_page;
-               off = (off + class->size) % PAGE_SIZE;
-       }
-}
-
-/*
- * Allocate a zspage for the given size class
- */
-static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
-{
-       int i, error;
-       struct page *first_page = NULL, *uninitialized_var(prev_page);
-
-       /*
-        * Allocate individual pages and link them together as:
-        * 1. first page->private = first sub-page
-        * 2. all sub-pages are linked together using page->lru
-        * 3. each sub-page is linked to the first page using page->first_page
-        *
-        * For each size class, First/Head pages are linked together using
-        * page->lru. Also, we set PG_private to identify the first page
-        * (i.e. no other sub-page has this flag set) and PG_private_2 to
-        * identify the last page.
-        */
-       error = -ENOMEM;
-       for (i = 0; i < class->pages_per_zspage; i++) {
-               struct page *page;
-
-               page = alloc_page(flags);
-               if (!page)
-                       goto cleanup;
-
-               INIT_LIST_HEAD(&page->lru);
-               if (i == 0) {   /* first page */
-                       SetPagePrivate(page);
-                       set_page_private(page, 0);
-                       first_page = page;
-                       first_page->inuse = 0;
-               }
-               if (i == 1)
-                       first_page->private = (unsigned long)page;
-               if (i >= 1)
-                       page->first_page = first_page;
-               if (i >= 2)
-                       list_add(&page->lru, &prev_page->lru);
-               if (i == class->pages_per_zspage - 1)   /* last page */
-                       SetPagePrivate2(page);
-               prev_page = page;
-       }
-
-       init_zspage(first_page, class);
-
-       first_page->freelist = obj_location_to_handle(first_page, 0);
-       /* Maximum number of objects we can store in this zspage */
-       first_page->objects = class->pages_per_zspage * PAGE_SIZE / class->size;
-
-       error = 0; /* Success */
-
-cleanup:
-       if (unlikely(error) && first_page) {
-               free_zspage(first_page);
-               first_page = NULL;
-       }
-
-       return first_page;
-}
-
-static struct page *find_get_zspage(struct size_class *class)
-{
-       int i;
-       struct page *page;
-
-       for (i = 0; i < _ZS_NR_FULLNESS_GROUPS; i++) {
-               page = class->fullness_list[i];
-               if (page)
-                       break;
-       }
-
-       return page;
-}
-
-#ifdef USE_PGTABLE_MAPPING
-static inline int __zs_cpu_up(struct mapping_area *area)
-{
-       /*
-        * Make sure we don't leak memory if a cpu UP notification
-        * and zs_init() race and both call zs_cpu_up() on the same cpu
-        */
-       if (area->vm)
-               return 0;
-       area->vm = alloc_vm_area(PAGE_SIZE * 2, NULL);
-       if (!area->vm)
-               return -ENOMEM;
-       return 0;
-}
-
-static inline void __zs_cpu_down(struct mapping_area *area)
-{
-       if (area->vm)
-               free_vm_area(area->vm);
-       area->vm = NULL;
-}
-
-static inline void *__zs_map_object(struct mapping_area *area,
-                               struct page *pages[2], int off, int size)
-{
-       BUG_ON(map_vm_area(area->vm, PAGE_KERNEL, &pages));
-       area->vm_addr = area->vm->addr;
-       return area->vm_addr + off;
-}
-
-static inline void __zs_unmap_object(struct mapping_area *area,
-                               struct page *pages[2], int off, int size)
-{
-       unsigned long addr = (unsigned long)area->vm_addr;
-
-       unmap_kernel_range(addr, PAGE_SIZE * 2);
-}
-
-#else /* USE_PGTABLE_MAPPING */
-
-static inline int __zs_cpu_up(struct mapping_area *area)
-{
-       /*
-        * Make sure we don't leak memory if a cpu UP notification
-        * and zs_init() race and both call zs_cpu_up() on the same cpu
-        */
-       if (area->vm_buf)
-               return 0;
-       area->vm_buf = (char *)__get_free_page(GFP_KERNEL);
-       if (!area->vm_buf)
-               return -ENOMEM;
-       return 0;
-}
-
-static inline void __zs_cpu_down(struct mapping_area *area)
-{
-       if (area->vm_buf)
-               free_page((unsigned long)area->vm_buf);
-       area->vm_buf = NULL;
-}
-
-static void *__zs_map_object(struct mapping_area *area,
-                       struct page *pages[2], int off, int size)
-{
-       int sizes[2];
-       void *addr;
-       char *buf = area->vm_buf;
-
-       /* disable page faults to match kmap_atomic() return conditions */
-       pagefault_disable();
-
-       /* no read fastpath */
-       if (area->vm_mm == ZS_MM_WO)
-               goto out;
-
-       sizes[0] = PAGE_SIZE - off;
-       sizes[1] = size - sizes[0];
-
-       /* copy object to per-cpu buffer */
-       addr = kmap_atomic(pages[0]);
-       memcpy(buf, addr + off, sizes[0]);
-       kunmap_atomic(addr);
-       addr = kmap_atomic(pages[1]);
-       memcpy(buf + sizes[0], addr, sizes[1]);
-       kunmap_atomic(addr);
-out:
-       return area->vm_buf;
-}
-
-static void __zs_unmap_object(struct mapping_area *area,
-                       struct page *pages[2], int off, int size)
-{
-       int sizes[2];
-       void *addr;
-       char *buf = area->vm_buf;
-
-       /* no write fastpath */
-       if (area->vm_mm == ZS_MM_RO)
-               goto out;
-
-       sizes[0] = PAGE_SIZE - off;
-       sizes[1] = size - sizes[0];
-
-       /* copy per-cpu buffer to object */
-       addr = kmap_atomic(pages[0]);
-       memcpy(addr + off, buf, sizes[0]);
-       kunmap_atomic(addr);
-       addr = kmap_atomic(pages[1]);
-       memcpy(addr, buf + sizes[0], sizes[1]);
-       kunmap_atomic(addr);
-
-out:
-       /* enable page faults to match kunmap_atomic() return conditions */
-       pagefault_enable();
-}
-
-#endif /* USE_PGTABLE_MAPPING */
-
-static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action,
-                               void *pcpu)
-{
-       int ret, cpu = (long)pcpu;
-       struct mapping_area *area;
-
-       switch (action) {
-       case CPU_UP_PREPARE:
-               area = &per_cpu(zs_map_area, cpu);
-               ret = __zs_cpu_up(area);
-               if (ret)
-                       return notifier_from_errno(ret);
-               break;
-       case CPU_DEAD:
-       case CPU_UP_CANCELED:
-               area = &per_cpu(zs_map_area, cpu);
-               __zs_cpu_down(area);
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block zs_cpu_nb = {
-       .notifier_call = zs_cpu_notifier
-};
-
-static void zs_exit(void)
-{
-       int cpu;
-
-       for_each_online_cpu(cpu)
-               zs_cpu_notifier(NULL, CPU_DEAD, (void *)(long)cpu);
-       unregister_cpu_notifier(&zs_cpu_nb);
-}
-
-static int zs_init(void)
-{
-       int cpu, ret;
-
-       register_cpu_notifier(&zs_cpu_nb);
-       for_each_online_cpu(cpu) {
-               ret = zs_cpu_notifier(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
-               if (notifier_to_errno(ret))
-                       goto fail;
-       }
-       return 0;
-fail:
-       zs_exit();
-       return notifier_to_errno(ret);
-}
-
-/**
- * zs_create_pool - Creates an allocation pool to work from.
- * @flags: allocation flags used to allocate pool metadata
- *
- * This function must be called before anything when using
- * the zsmalloc allocator.
- *
- * On success, a pointer to the newly created pool is returned,
- * otherwise NULL.
- */
-struct zs_pool *zs_create_pool(gfp_t flags)
-{
-       int i, ovhd_size;
-       struct zs_pool *pool;
-
-       ovhd_size = roundup(sizeof(*pool), PAGE_SIZE);
-       pool = kzalloc(ovhd_size, GFP_KERNEL);
-       if (!pool)
-               return NULL;
-
-       for (i = 0; i < ZS_SIZE_CLASSES; i++) {
-               int size;
-               struct size_class *class;
-
-               size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA;
-               if (size > ZS_MAX_ALLOC_SIZE)
-                       size = ZS_MAX_ALLOC_SIZE;
-
-               class = &pool->size_class[i];
-               class->size = size;
-               class->index = i;
-               spin_lock_init(&class->lock);
-               class->pages_per_zspage = get_pages_per_zspage(size);
-
-       }
-
-       pool->flags = flags;
-
-       return pool;
-}
-EXPORT_SYMBOL_GPL(zs_create_pool);
-
-void zs_destroy_pool(struct zs_pool *pool)
-{
-       int i;
-
-       for (i = 0; i < ZS_SIZE_CLASSES; i++) {
-               int fg;
-               struct size_class *class = &pool->size_class[i];
-
-               for (fg = 0; fg < _ZS_NR_FULLNESS_GROUPS; fg++) {
-                       if (class->fullness_list[fg]) {
-                               pr_info("Freeing non-empty class with size "
-                                       "%db, fullness group %d\n",
-                                       class->size, fg);
-                       }
-               }
-       }
-       kfree(pool);
-}
-EXPORT_SYMBOL_GPL(zs_destroy_pool);
-
-/**
- * zs_malloc - Allocate block of given size from pool.
- * @pool: pool to allocate from
- * @size: size of block to allocate
- *
- * On success, handle to the allocated object is returned,
- * otherwise 0.
- * Allocation requests with size > ZS_MAX_ALLOC_SIZE will fail.
- */
-unsigned long zs_malloc(struct zs_pool *pool, size_t size)
-{
-       unsigned long obj;
-       struct link_free *link;
-       int class_idx;
-       struct size_class *class;
-
-       struct page *first_page, *m_page;
-       unsigned long m_objidx, m_offset;
-
-       if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE))
-               return 0;
-
-       class_idx = get_size_class_index(size);
-       class = &pool->size_class[class_idx];
-       BUG_ON(class_idx != class->index);
-
-       spin_lock(&class->lock);
-       first_page = find_get_zspage(class);
-
-       if (!first_page) {
-               spin_unlock(&class->lock);
-               first_page = alloc_zspage(class, pool->flags);
-               if (unlikely(!first_page))
-                       return 0;
-
-               set_zspage_mapping(first_page, class->index, ZS_EMPTY);
-               spin_lock(&class->lock);
-               class->pages_allocated += class->pages_per_zspage;
-       }
-
-       obj = (unsigned long)first_page->freelist;
-       obj_handle_to_location(obj, &m_page, &m_objidx);
-       m_offset = obj_idx_to_offset(m_page, m_objidx, class->size);
-
-       link = (struct link_free *)kmap_atomic(m_page) +
-                                       m_offset / sizeof(*link);
-       first_page->freelist = link->next;
-       memset(link, POISON_INUSE, sizeof(*link));
-       kunmap_atomic(link);
-
-       first_page->inuse++;
-       /* Now move the zspage to another fullness group, if required */
-       fix_fullness_group(pool, first_page);
-       spin_unlock(&class->lock);
-
-       return obj;
-}
-EXPORT_SYMBOL_GPL(zs_malloc);
-
-void zs_free(struct zs_pool *pool, unsigned long obj)
-{
-       struct link_free *link;
-       struct page *first_page, *f_page;
-       unsigned long f_objidx, f_offset;
-
-       int class_idx;
-       struct size_class *class;
-       enum fullness_group fullness;
-
-       if (unlikely(!obj))
-               return;
-
-       obj_handle_to_location(obj, &f_page, &f_objidx);
-       first_page = get_first_page(f_page);
-
-       get_zspage_mapping(first_page, &class_idx, &fullness);
-       class = &pool->size_class[class_idx];
-       f_offset = obj_idx_to_offset(f_page, f_objidx, class->size);
-
-       spin_lock(&class->lock);
-
-       /* Insert this object in containing zspage's freelist */
-       link = (struct link_free *)((unsigned char *)kmap_atomic(f_page)
-                                                       + f_offset);
-       link->next = first_page->freelist;
-       kunmap_atomic(link);
-       first_page->freelist = (void *)obj;
-
-       first_page->inuse--;
-       fullness = fix_fullness_group(pool, first_page);
-
-       if (fullness == ZS_EMPTY)
-               class->pages_allocated -= class->pages_per_zspage;
-
-       spin_unlock(&class->lock);
-
-       if (fullness == ZS_EMPTY)
-               free_zspage(first_page);
-}
-EXPORT_SYMBOL_GPL(zs_free);
-
-/**
- * zs_map_object - get address of allocated object from handle.
- * @pool: pool from which the object was allocated
- * @handle: handle returned from zs_malloc
- *
- * Before using an object allocated from zs_malloc, it must be mapped using
- * this function. When done with the object, it must be unmapped using
- * zs_unmap_object.
- *
- * Only one object can be mapped per cpu at a time. There is no protection
- * against nested mappings.
- *
- * This function returns with preemption and page faults disabled.
-*/
-void *zs_map_object(struct zs_pool *pool, unsigned long handle,
-                       enum zs_mapmode mm)
-{
-       struct page *page;
-       unsigned long obj_idx, off;
-
-       unsigned int class_idx;
-       enum fullness_group fg;
-       struct size_class *class;
-       struct mapping_area *area;
-       struct page *pages[2];
-
-       BUG_ON(!handle);
-
-       /*
-        * Because we use per-cpu mapping areas shared among the
-        * pools/users, we can't allow mapping in interrupt context
-        * because it can corrupt another users mappings.
-        */
-       BUG_ON(in_interrupt());
-
-       obj_handle_to_location(handle, &page, &obj_idx);
-       get_zspage_mapping(get_first_page(page), &class_idx, &fg);
-       class = &pool->size_class[class_idx];
-       off = obj_idx_to_offset(page, obj_idx, class->size);
-
-       area = &get_cpu_var(zs_map_area);
-       area->vm_mm = mm;
-       if (off + class->size <= PAGE_SIZE) {
-               /* this object is contained entirely within a page */
-               area->vm_addr = kmap_atomic(page);
-               return area->vm_addr + off;
-       }
-
-       /* this object spans two pages */
-       pages[0] = page;
-       pages[1] = get_next_page(page);
-       BUG_ON(!pages[1]);
-
-       return __zs_map_object(area, pages, off, class->size);
-}
-EXPORT_SYMBOL_GPL(zs_map_object);
-
-void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
-{
-       struct page *page;
-       unsigned long obj_idx, off;
-
-       unsigned int class_idx;
-       enum fullness_group fg;
-       struct size_class *class;
-       struct mapping_area *area;
-
-       BUG_ON(!handle);
-
-       obj_handle_to_location(handle, &page, &obj_idx);
-       get_zspage_mapping(get_first_page(page), &class_idx, &fg);
-       class = &pool->size_class[class_idx];
-       off = obj_idx_to_offset(page, obj_idx, class->size);
-
-       area = &__get_cpu_var(zs_map_area);
-       if (off + class->size <= PAGE_SIZE)
-               kunmap_atomic(area->vm_addr);
-       else {
-               struct page *pages[2];
-
-               pages[0] = page;
-               pages[1] = get_next_page(page);
-               BUG_ON(!pages[1]);
-
-               __zs_unmap_object(area, pages, off, class->size);
-       }
-       put_cpu_var(zs_map_area);
-}
-EXPORT_SYMBOL_GPL(zs_unmap_object);
-
-u64 zs_get_total_size_bytes(struct zs_pool *pool)
-{
-       int i;
-       u64 npages = 0;
-
-       for (i = 0; i < ZS_SIZE_CLASSES; i++)
-               npages += pool->size_class[i].pages_allocated;
-
-       return npages << PAGE_SHIFT;
-}
-EXPORT_SYMBOL_GPL(zs_get_total_size_bytes);
-
-module_init(zs_init);
-module_exit(zs_exit);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
diff --git a/drivers/staging/zsmalloc/zsmalloc.h b/drivers/staging/zsmalloc/zsmalloc.h
deleted file mode 100644 (file)
index 46dbd05..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * zsmalloc memory allocator
- *
- * Copyright (C) 2011  Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the license that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- */
-
-#ifndef _ZS_MALLOC_H_
-#define _ZS_MALLOC_H_
-
-#include <linux/types.h>
-
-/*
- * zsmalloc mapping modes
- *
- * NOTE: These only make a difference when a mapped object spans pages
-*/
-enum zs_mapmode {
-       ZS_MM_RW, /* normal read-write mapping */
-       ZS_MM_RO, /* read-only (no copy-out at unmap time) */
-       ZS_MM_WO /* write-only (no copy-in at map time) */
-};
-
-struct zs_pool;
-
-struct zs_pool *zs_create_pool(gfp_t flags);
-void zs_destroy_pool(struct zs_pool *pool);
-
-unsigned long zs_malloc(struct zs_pool *pool, size_t size);
-void zs_free(struct zs_pool *pool, unsigned long obj);
-
-void *zs_map_object(struct zs_pool *pool, unsigned long handle,
-                       enum zs_mapmode mm);
-void zs_unmap_object(struct zs_pool *pool, unsigned long handle);
-
-u64 zs_get_total_size_bytes(struct zs_pool *pool);
-
-#endif
index 9559ea749d83e7275d31a5335d23bb8f032f41ac..5a3ea20e9cb52670c150d39a25f88af4a5149107 100644 (file)
@@ -1179,7 +1179,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * traditional iSCSI block I/O.
         */
        if (iscsit_allocate_iovecs(cmd) < 0) {
-               return iscsit_add_reject_cmd(cmd,
+               return iscsit_reject_cmd(cmd,
                                ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
        }
        immed_data = cmd->immediate_data;
index 4fc32c8091e982d626cfe6506fa0c804ca7cd3f3..ff92155dbc88c6e026482e7c3afad1a7b9c6ea30 100644 (file)
@@ -299,11 +299,27 @@ static int xen_initial_domain_console_init(void)
        return 0;
 }
 
+static void xen_console_update_evtchn(struct xencons_info *info)
+{
+       if (xen_hvm_domain()) {
+               uint64_t v;
+               int err;
+
+               err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+               if (!err && v)
+                       info->evtchn = v;
+       } else
+               info->evtchn = xen_start_info->console.domU.evtchn;
+}
+
 void xen_console_resume(void)
 {
        struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE);
-       if (info != NULL && info->irq)
+       if (info != NULL && info->irq) {
+               if (!xen_initial_domain())
+                       xen_console_update_evtchn(info);
                rebind_evtchn_irq(info->evtchn, info->irq);
+       }
 }
 
 static void xencons_disconnect_backend(struct xencons_info *info)
index 345b5ddcb1a01285f1c0d57af88771cedd15b4ea..86281fa5dcc327424e3ca9a3115e8032874c6147 100644 (file)
@@ -98,7 +98,10 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
                        dw8250_force_idle(p);
                        writeb(value, p->membase + (UART_LCR << p->regshift));
                }
-               dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+               /*
+                * FIXME: this deadlocks if port->lock is already held
+                * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+                */
        }
 }
 
@@ -128,7 +131,10 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
                        dw8250_force_idle(p);
                        writel(value, p->membase + (UART_LCR << p->regshift));
                }
-               dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+               /*
+                * FIXME: this deadlocks if port->lock is already held
+                * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+                */
        }
 }
 
index 39c7ea4cb14fb9e95fbc920d86010f39db2aa691..2225f83f4c04cc323da874191d8f4698d32cf6d9 100644 (file)
@@ -262,7 +262,6 @@ static struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ibm,qpace-nwp-serial",
                .data = (void *)PORT_NWPSERIAL, },
 #endif
-       { .type = "serial",         .data = (void *)PORT_UNKNOWN, },
        { /* end of list */ },
 };
 
index 6463ca3bcfbacee84d0155291f10df812f650940..07133d0c971b441d000a5d3b32fe9af5eb5a1787 100644 (file)
@@ -244,7 +244,7 @@ static void wdm_int_callback(struct urb *urb)
        case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
                dev_dbg(&desc->intf->dev,
                        "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d",
-                       dr->wIndex, dr->wLength);
+                       le16_to_cpu(dr->wIndex), le16_to_cpu(dr->wLength));
                break;
 
        case USB_CDC_NOTIFY_NETWORK_CONNECTION:
@@ -257,7 +257,9 @@ static void wdm_int_callback(struct urb *urb)
                clear_bit(WDM_POLL_RUNNING, &desc->flags);
                dev_err(&desc->intf->dev,
                        "unknown notification %d received: index %d len %d\n",
-                       dr->bNotificationType, dr->wIndex, dr->wLength);
+                       dr->bNotificationType,
+                       le16_to_cpu(dr->wIndex),
+                       le16_to_cpu(dr->wLength));
                goto exit;
        }
 
@@ -403,7 +405,7 @@ static ssize_t wdm_write
                             USB_RECIP_INTERFACE);
        req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
        req->wValue = 0;
-       req->wIndex = desc->inum;
+       req->wIndex = desc->inum; /* already converted */
        req->wLength = cpu_to_le16(count);
        set_bit(WDM_IN_USE, &desc->flags);
        desc->outbuf = buf;
@@ -417,7 +419,7 @@ static ssize_t wdm_write
                rv = usb_translate_errors(rv);
        } else {
                dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
-                       req->wIndex);
+                       le16_to_cpu(req->wIndex));
        }
 out:
        usb_autopm_put_interface(desc->intf);
@@ -780,7 +782,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
        desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
        desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
        desc->irq->wValue = 0;
-       desc->irq->wIndex = desc->inum;
+       desc->irq->wIndex = desc->inum; /* already converted */
        desc->irq->wLength = cpu_to_le16(desc->wMaxCommand);
 
        usb_fill_control_urb(
index 2260781b50af26e5be83c84b7f6f72aa415a939f..da1fe23c1f0aa706fd2b46583472b0aa7d375c92 100755 (executable)
@@ -3286,10 +3286,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
                dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
                                port1, status);
        } else {
-               /* drive resume for at least 20 msec */
+               /* drive resume for USB_RESUME_TIMEOUT msec */
                dev_dbg(&udev->dev, "usb %sresume\n",
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""));
-               msleep(25);
+               msleep(USB_RESUME_TIMEOUT);
 
                /* Virtual root hubs can trigger on GET_PORT_STATUS to
                 * stop resume signaling.  Then finish the resume
index 0ef3cdf97e6a10239c64e43e51cf4eb5bed51ee3..7b899e1db5f7c443760ef9f21dfcf1d485025043 100755 (executable)
@@ -820,6 +820,9 @@ config USB_G_PRINTER
 
 config USB_G_ANDROID
        boolean "Android Composite Gadget"
+       depends on SND
+       select SND_PCM
+       select SND_RAWMIDI
        select USB_F_ACM
        select USB_LIBCOMPOSITE
        select USB_U_SERIAL
index fd045a6d04e1ceacc1a9546f07597edf20c2f8a4..987a1e08ec7306cef1f86b5565780afc8b789d30 100644 (file)
@@ -529,7 +529,7 @@ static int bos_desc(struct usb_composite_dev *cdev)
        usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
        usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
        usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
-       usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
+       usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
 
        /*
         * The Superspeed USB Capability descriptor shall be implemented by all
index bf7a56b6d48ac2c3ebb3acf8920c70d79900d307..a0dfdbddbf085e786098874f6f80171918b18abb 100644 (file)
@@ -975,6 +975,15 @@ unknown:
                break;
        }
        /* host either stalls (value < 0) or reports success */
+       if (value >= 0) {
+               req->length = value;
+               req->zero = value < wLength;
+               value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+               if (value < 0) {
+                       ERROR(dev, "%s:%d Error!\n", __func__, __LINE__);
+                       req->status = 0;
+               }
+       }
        return value;
 }
 
index b64e661618bb8842bea5ad02f3d8444453a71c9b..baf2807934c101712b675a2ea91828ab4ee4e3d8 100644 (file)
@@ -1488,7 +1488,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
        spin_unlock_irq(&isp116x->lock);
 
        hcd->state = HC_STATE_RESUMING;
-       msleep(20);
+       msleep(USB_RESUME_TIMEOUT);
 
        /* Go operational */
        spin_lock_irq(&isp116x->lock);
index 0f401dbfaf073bb59f7faad445a19663bded3a0e..b5c4f4d81a384f3b2318bab0638bd7345ea20910 100644 (file)
@@ -2497,11 +2497,12 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
                                        || oxu->reset_done[i] != 0)
                                continue;
 
-                       /* start 20 msec resume signaling from this port,
-                        * and make khubd collect PORT_STAT_C_SUSPEND to
+                       /* start USB_RESUME_TIMEOUT resume signaling from this
+                        * port, and make hub_wq collect PORT_STAT_C_SUSPEND to
                         * stop that signaling.
                         */
-                       oxu->reset_done[i] = jiffies + msecs_to_jiffies(20);
+                       oxu->reset_done[i] = jiffies +
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        oxu_dbg(oxu, "port %d remote wakeup\n", i + 1);
                        mod_timer(&hcd->rh_timer, oxu->reset_done[i]);
                }
index a6fd8f5371dfd9f7c534fbf73ff2cc815f1bbdb1..6656dfda5665768930291c591c4121cef282030c 100644 (file)
@@ -2301,7 +2301,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
                rh->port &= ~USB_PORT_STAT_SUSPEND;
                rh->port |= USB_PORT_STAT_C_SUSPEND << 16;
                r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
-               msleep(50);
+               msleep(USB_RESUME_TIMEOUT);
                r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
        }
 
index b2ec7fe758ddcf3dba22f922493ca6cebdeaea10..b4cad934603549cb44a8acd66999fd7004ac5def 100644 (file)
@@ -1251,7 +1251,7 @@ sl811h_hub_control(
                        sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
 
                        mod_timer(&sl811->timer, jiffies
-                                       + msecs_to_jiffies(20));
+                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT));
                        break;
                case USB_PORT_FEAT_POWER:
                        port_power(sl811, 0);
index 0e57bcb8e3f79a3c464eda255d322f8a876770c2..2320e20d5be74312d37292d943b58c23f04d677c 100644 (file)
@@ -94,6 +94,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                xhci->quirks |= XHCI_LPM_SUPPORT;
                xhci->quirks |= XHCI_INTEL_HOST;
+               xhci->quirks |= XHCI_AVOID_BEI;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                        pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) {
@@ -109,7 +110,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 * PPT chipsets.
                 */
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
-               xhci->quirks |= XHCI_AVOID_BEI;
        }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
index 9948890ef93efdb9cf0437714e6be2e906e80632..bc7a886e3c36ddb76b4b9f1c624b4e75db837aca 100644 (file)
@@ -1697,7 +1697,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                } else {
                        xhci_dbg(xhci, "resume HS port %d\n", port_id);
                        bus_state->resume_done[faked_port_index] = jiffies +
-                               msecs_to_jiffies(20);
+                               msecs_to_jiffies(USB_RESUME_TIMEOUT);
                        set_bit(faked_port_index, &bus_state->resuming_ports);
                        mod_timer(&hcd->rh_timer,
                                  bus_state->resume_done[faked_port_index]);
index a9984c700d2c428fd2e771a1d175c12009f94475..5f79d8e2caab76219edc887e936f94045d154cf7 100644 (file)
@@ -78,7 +78,9 @@ static void devm_usb_phy_release(struct device *dev, void *res)
 
 static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
 {
-       return res == match_data;
+       struct usb_phy **phy = res;
+
+       return *phy == match_data;
 }
 
 /**
index cf127a080644bdb1693fe42a38365bd27ed95626..4d918d5f945a096d6c12deee12b78c2d3a0a8a30 100644 (file)
@@ -620,6 +620,7 @@ static struct usb_device_id id_table_combined [] = {
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
        /*
         * ELV devices:
         */
@@ -1899,8 +1900,12 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
 {
        struct usb_device *udev = serial->dev;
 
-       if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
-           (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2")))
+       if (udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems"))
+               return ftdi_jtag_probe(serial);
+
+       if (udev->product &&
+               (!strcmp(udev->product, "BeagleBone/XDS100V2") ||
+                !strcmp(udev->product, "SNAP Connect E10")))
                return ftdi_jtag_probe(serial);
 
        return 0;
index e8d3526152976087066be912ca4bbfbe541b73c0..e906b6aa24244da3e535b27c6904bcac020d46f9 100644 (file)
  */
 #define FTDI_NT_ORIONLXM_PID   0x7c90  /* OrionLXm Substation Automation Platform */
 
+/*
+ * Synapse Wireless product ids (FTDI_VID)
+ * http://www.synapse-wireless.com
+ */
+#define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */
+
 
 /********************************/
 /** third-party VID/PID combos **/
index d5fa5f3fe6d1b2e02ad79ddf8bb857806122ca12..37e62c7b3273e8d4b5c3c8be1658504ebc5910ff 100644 (file)
@@ -6,7 +6,10 @@ menu "Console display driver support"
 
 config VGA_CONSOLE
        bool "VGA text console" if EXPERT || !X86
-       depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && !ARM64
+       depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && \
+               !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && !CRIS && \
+               (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && \
+               !ARM64
        default y
        help
          Saying Y here will allow you to use Linux in text mode through a
index d9a43674cb9479eb673140121e60ee0355acf409..9cca0ea4e47909a11a91eebf48653c957d68f5b1 100644 (file)
@@ -126,7 +126,7 @@ affs_fix_dcache(struct inode *inode, u32 entry_ino)
 {
        struct dentry *dentry;
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                if (entry_ino == (u32)(long)dentry->d_fsdata) {
                        dentry->d_fsdata = (void *)inode->i_ino;
                        break;
index 13ddec92341cdaaa63cf811ee1037a2038994191..8ad277990eacc37236a57c9c3415853dc8806505 100644 (file)
@@ -91,7 +91,7 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev,
        spin_lock(&root->d_lock);
 
        if (prev)
-               next = prev->d_u.d_child.next;
+               next = prev->d_child.next;
        else {
                prev = dget_dlock(root);
                next = prev->d_subdirs.next;
@@ -105,13 +105,13 @@ cont:
                return NULL;
        }
 
-       q = list_entry(next, struct dentry, d_u.d_child);
+       q = list_entry(next, struct dentry, d_child);
 
        spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED);
        /* Already gone or negative dentry (under construction) - try next */
        if (q->d_count == 0 || !simple_positive(q)) {
                spin_unlock(&q->d_lock);
-               next = q->d_u.d_child.next;
+               next = q->d_child.next;
                goto cont;
        }
        dget_dlock(q);
@@ -161,13 +161,13 @@ again:
                                goto relock;
                        }
                        spin_unlock(&p->d_lock);
-                       next = p->d_u.d_child.next;
+                       next = p->d_child.next;
                        p = parent;
                        if (next != &parent->d_subdirs)
                                break;
                }
        }
-       ret = list_entry(next, struct dentry, d_u.d_child);
+       ret = list_entry(next, struct dentry, d_child);
 
        spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
        /* Negative dentry - try next */
@@ -447,7 +447,7 @@ found:
        spin_lock(&sbi->lookup_lock);
        spin_lock(&expired->d_parent->d_lock);
        spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
-       list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
+       list_move(&expired->d_parent->d_subdirs, &expired->d_child);
        spin_unlock(&expired->d_lock);
        spin_unlock(&expired->d_parent->d_lock);
        spin_unlock(&sbi->lookup_lock);
index 085da86e07c22031f14b999d6caaf77063dfbde7..79ab4cb3590a4f690764b3f52e9a25771b8147d6 100644 (file)
@@ -655,7 +655,7 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
        /* only consider parents below dentrys in the root */
        if (IS_ROOT(parent->d_parent))
                return;
-       d_child = &dentry->d_u.d_child;
+       d_child = &dentry->d_child;
        /* Set parent managed if it's becoming empty */
        if (d_child->next == &parent->d_subdirs &&
            d_child->prev == &parent->d_subdirs)
index 3c4d8797ea9aa3218313cb1e89065cce649fc91d..53f620a4350e3d02272c721a6bf3647e5f4757c7 100644 (file)
@@ -756,6 +756,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
            i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
                int elf_prot = 0, elf_flags;
                unsigned long k, vaddr;
+               unsigned long total_size = 0;
 
                if (elf_ppnt->p_type != PT_LOAD)
                        continue;
@@ -820,10 +821,16 @@ static int load_elf_binary(struct linux_binprm *bprm)
 #else
                        load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 #endif
+                       total_size = total_mapping_size(elf_phdata,
+                                                       loc->elf_ex.e_phnum);
+                       if (!total_size) {
+                               error = -EINVAL;
+                               goto out_free_dentry;
+                       }
                }
 
                error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-                               elf_prot, elf_flags, 0);
+                               elf_prot, elf_flags, total_size);
                if (BAD_ADDR(error)) {
                        send_sig(SIGKILL, current, 0);
                        retval = IS_ERR((void *)error) ?
index f99c71e40f8b86a91a73c4ace7a17f933c4de464..07f167a1d27141873a962566d66c796c45d42be5 100644 (file)
@@ -6363,12 +6363,11 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
                return -ENOSPC;
        }
 
-       if (btrfs_test_opt(root, DISCARD))
-               ret = btrfs_discard_extent(root, start, len, NULL);
-
        if (pin)
                pin_down_extent(root, cache, start, len, 1);
        else {
+               if (btrfs_test_opt(root, DISCARD))
+                       ret = btrfs_discard_extent(root, start, len, NULL);
                btrfs_add_free_space(cache, start, len);
                btrfs_update_reserved_bytes(cache, len, RESERVE_FREE);
        }
index 783906c687b55de0053adf46754d2630e8dd9e83..dbefa6c609f47bfb363c5e64399bd770cc9b10fc 100644 (file)
@@ -2572,6 +2572,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
        if (off + len == src->i_size)
                len = ALIGN(src->i_size, bs) - off;
 
+       if (len == 0) {
+               ret = 0;
+               goto out_unlock;
+       }
+
        /* verify the end result is block aligned */
        if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
            !IS_ALIGNED(destoff, bs))
index f02d82b7933e4399abd235a2527403df3364a2fa..ccb43298e272dcadb76bea25ddd6287f420f5bdd 100644 (file)
@@ -103,7 +103,7 @@ static unsigned fpos_off(loff_t p)
 /*
  * When possible, we try to satisfy a readdir by peeking at the
  * dcache.  We make this work by carefully ordering dentries on
- * d_u.d_child when we initially get results back from the MDS, and
+ * d_child when we initially get results back from the MDS, and
  * falling back to a "normal" sync readdir if any dentries in the dir
  * are dropped.
  *
@@ -139,11 +139,11 @@ static int __dcache_readdir(struct file *filp,
                p = parent->d_subdirs.prev;
                dout(" initial p %p/%p\n", p->prev, p->next);
        } else {
-               p = last->d_u.d_child.prev;
+               p = last->d_child.prev;
        }
 
 more:
-       dentry = list_entry(p, struct dentry, d_u.d_child);
+       dentry = list_entry(p, struct dentry, d_child);
        di = ceph_dentry(dentry);
        while (1) {
                dout(" p %p/%p %s d_subdirs %p/%p\n", p->prev, p->next,
@@ -165,7 +165,7 @@ more:
                     !dentry->d_inode ? " null" : "");
                spin_unlock(&dentry->d_lock);
                p = p->prev;
-               dentry = list_entry(p, struct dentry, d_u.d_child);
+               dentry = list_entry(p, struct dentry, d_child);
                di = ceph_dentry(dentry);
        }
 
index be0f7e20d62ed230186019d65297e8f45f2f4ab2..0cf23a7b88c2e302dd8d85522e0968b9c00f07f6 100644 (file)
@@ -867,9 +867,9 @@ static void ceph_set_dentry_offset(struct dentry *dn)
 
        spin_lock(&dir->d_lock);
        spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
-       list_move(&dn->d_u.d_child, &dir->d_subdirs);
+       list_move(&dn->d_child, &dir->d_subdirs);
        dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
-            dn->d_u.d_child.prev, dn->d_u.d_child.next);
+            dn->d_child.prev, dn->d_child.next);
        spin_unlock(&dn->d_lock);
        spin_unlock(&dir->d_lock);
 }
@@ -1296,7 +1296,7 @@ retry_lookup:
                        /* reorder parent's d_subdirs */
                        spin_lock(&parent->d_lock);
                        spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
-                       list_move(&dn->d_u.d_child, &parent->d_subdirs);
+                       list_move(&dn->d_child, &parent->d_subdirs);
                        spin_unlock(&dn->d_lock);
                        spin_unlock(&parent->d_lock);
                }
index 5fcc10fa62bd768d4858d0d2c3a4dae42bfb8bd1..f4a8577c3e91369e55f0dd7b3466faa5c78a773d 100644 (file)
@@ -1789,6 +1789,7 @@ refind_writable:
                        cifsFileInfo_put(inv_file);
                        spin_lock(&cifs_file_list_lock);
                        ++refind;
+                       inv_file = NULL;
                        goto refind_writable;
                }
        }
index 0dee93706c9828b49e947820bb9ae05ff85b6198..54304ccae7e7d0e4b90d75aab0fe01bbee29bfc4 100644 (file)
@@ -832,7 +832,7 @@ inode_has_hashed_dentries(struct inode *inode)
        struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
                        spin_unlock(&inode->i_lock);
                        return true;
index 1da168c61d35c2194422fa24c5bca3235a1c19ca..9bc1147a6c5d4d5666f948500d1ec0ccbc4413b4 100644 (file)
@@ -92,7 +92,7 @@ static void coda_flag_children(struct dentry *parent, int flag)
        struct dentry *de;
 
        spin_lock(&parent->d_lock);
-       list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(de, &parent->d_subdirs, d_child) {
                /* don't know what to do with negative dentries */
                if (de->d_inode ) 
                        coda_flag_inode(de->d_inode, flag);
index 25c0a1b5f6c0ecab691c8081f1f282dacb44175a..efa4602e064f75d47f064ab74084f8b81f5cc56b 100644 (file)
@@ -43,7 +43,7 @@
 /*
  * Usage:
  * dcache->d_inode->i_lock protects:
- *   - i_dentry, d_alias, d_inode of aliases
+ *   - i_dentry, d_u.d_alias, d_inode of aliases
  * dcache_hash_bucket lock protects:
  *   - the dcache hash table
  * s_anon bl list spinlock protects:
@@ -58,7 +58,7 @@
  *   - d_unhashed()
  *   - d_parent and d_subdirs
  *   - childrens' d_child and d_parent
- *   - d_alias, d_inode
+ *   - d_u.d_alias, d_inode
  *
  * Ordering:
  * dentry->d_inode->i_lock
@@ -215,7 +215,6 @@ static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
 
-       WARN_ON(!hlist_unhashed(&dentry->d_alias));
        if (dname_external(dentry))
                kfree(dentry->d_name.name);
        kmem_cache_free(dentry_cache, dentry); 
@@ -226,6 +225,7 @@ static void __d_free(struct rcu_head *head)
  */
 static void d_free(struct dentry *dentry)
 {
+       WARN_ON(!hlist_unhashed(&dentry->d_u.d_alias));
        BUG_ON(dentry->d_count);
        this_cpu_dec(nr_dentry);
        if (dentry->d_op && dentry->d_op->d_release)
@@ -264,7 +264,7 @@ static void dentry_iput(struct dentry * dentry)
        struct inode *inode = dentry->d_inode;
        if (inode) {
                dentry->d_inode = NULL;
-               hlist_del_init(&dentry->d_alias);
+               hlist_del_init(&dentry->d_u.d_alias);
                spin_unlock(&dentry->d_lock);
                spin_unlock(&inode->i_lock);
                if (!inode->i_nlink)
@@ -288,7 +288,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
 {
        struct inode *inode = dentry->d_inode;
        dentry->d_inode = NULL;
-       hlist_del_init(&dentry->d_alias);
+       hlist_del_init(&dentry->d_u.d_alias);
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&inode->i_lock);
@@ -364,9 +364,9 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
        __releases(parent->d_lock)
        __releases(dentry->d_inode->i_lock)
 {
-       list_del(&dentry->d_u.d_child);
+       __list_del_entry(&dentry->d_child);
        /*
-        * Inform try_to_ascend() that we are no longer attached to the
+        * Inform ascending readers that we are no longer attached to the
         * dentry tree
         */
        dentry->d_flags |= DCACHE_DENTRY_KILLED;
@@ -660,7 +660,7 @@ static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
 
 again:
        discon_alias = NULL;
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&alias->d_lock);
                if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
                        if (IS_ROOT(alias) &&
@@ -713,7 +713,7 @@ void d_prune_aliases(struct inode *inode)
        struct dentry *dentry;
 restart:
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (!dentry->d_count) {
                        __dget_dlock(dentry);
@@ -893,7 +893,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                /* descend to the first leaf in the current subtree */
                while (!list_empty(&dentry->d_subdirs))
                        dentry = list_entry(dentry->d_subdirs.next,
-                                           struct dentry, d_u.d_child);
+                                           struct dentry, d_child);
 
                /* consume the dentries from this leaf up through its parents
                 * until we find one with children or run out altogether */
@@ -927,17 +927,17 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
 
                        if (IS_ROOT(dentry)) {
                                parent = NULL;
-                               list_del(&dentry->d_u.d_child);
+                               list_del(&dentry->d_child);
                        } else {
                                parent = dentry->d_parent;
                                parent->d_count--;
-                               list_del(&dentry->d_u.d_child);
+                               list_del(&dentry->d_child);
                        }
 
                        inode = dentry->d_inode;
                        if (inode) {
                                dentry->d_inode = NULL;
-                               hlist_del_init(&dentry->d_alias);
+                               hlist_del_init(&dentry->d_u.d_alias);
                                if (dentry->d_op && dentry->d_op->d_iput)
                                        dentry->d_op->d_iput(dentry, inode);
                                else
@@ -955,7 +955,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                } while (list_empty(&dentry->d_subdirs));
 
                dentry = list_entry(dentry->d_subdirs.next,
-                                   struct dentry, d_u.d_child);
+                                   struct dentry, d_child);
        }
 }
 
@@ -987,35 +987,6 @@ void shrink_dcache_for_umount(struct super_block *sb)
        }
 }
 
-/*
- * This tries to ascend one level of parenthood, but
- * we can race with renaming, so we need to re-check
- * the parenthood after dropping the lock and check
- * that the sequence number still matches.
- */
-static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq)
-{
-       struct dentry *new = old->d_parent;
-
-       rcu_read_lock();
-       spin_unlock(&old->d_lock);
-       spin_lock(&new->d_lock);
-
-       /*
-        * might go back up the wrong parent if we have had a rename
-        * or deletion
-        */
-       if (new != old->d_parent ||
-                (old->d_flags & DCACHE_DENTRY_KILLED) ||
-                (!locked && read_seqretry(&rename_lock, seq))) {
-               spin_unlock(&new->d_lock);
-               new = NULL;
-       }
-       rcu_read_unlock();
-       return new;
-}
-
-
 /*
  * Search for at least 1 mount point in the dentry's subdirs.
  * We descend to the next level whenever the d_subdirs
@@ -1048,7 +1019,7 @@ repeat:
 resume:
        while (next != &this_parent->d_subdirs) {
                struct list_head *tmp = next;
-               struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
+               struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
                next = tmp->next;
 
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -1070,30 +1041,48 @@ resume:
        /*
         * All done at this level ... ascend and resume the search.
         */
+       rcu_read_lock();
+ascend:
        if (this_parent != parent) {
                struct dentry *child = this_parent;
-               this_parent = try_to_ascend(this_parent, locked, seq);
-               if (!this_parent)
+               this_parent = child->d_parent;
+
+               spin_unlock(&child->d_lock);
+               spin_lock(&this_parent->d_lock);
+
+               /* might go back up the wrong parent if we have had a rename. */
+               if (!locked && read_seqretry(&rename_lock, seq))
                        goto rename_retry;
-               next = child->d_u.d_child.next;
+               next = child->d_child.next;
+               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+                       if (next == &this_parent->d_subdirs)
+                               goto ascend;
+                       child = list_entry(next, struct dentry, d_child);
+                       next = next->next;
+               }
+               rcu_read_unlock();
                goto resume;
        }
-       spin_unlock(&this_parent->d_lock);
        if (!locked && read_seqretry(&rename_lock, seq))
                goto rename_retry;
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
        if (locked)
                write_sequnlock(&rename_lock);
        return 0; /* No mount points found in tree */
 positive:
        if (!locked && read_seqretry(&rename_lock, seq))
-               goto rename_retry;
+               goto rename_retry_unlocked;
        if (locked)
                write_sequnlock(&rename_lock);
        return 1;
 
 rename_retry:
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
        if (locked)
                goto again;
+rename_retry_unlocked:
        locked = 1;
        write_seqlock(&rename_lock);
        goto again;
@@ -1131,7 +1120,7 @@ repeat:
 resume:
        while (next != &this_parent->d_subdirs) {
                struct list_head *tmp = next;
-               struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
+               struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
                next = tmp->next;
 
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -1158,6 +1147,7 @@ resume:
                 */
                if (found && need_resched()) {
                        spin_unlock(&dentry->d_lock);
+                       rcu_read_lock();
                        goto out;
                }
 
@@ -1177,23 +1167,40 @@ resume:
        /*
         * All done at this level ... ascend and resume the search.
         */
+       rcu_read_lock();
+ascend:
        if (this_parent != parent) {
                struct dentry *child = this_parent;
-               this_parent = try_to_ascend(this_parent, locked, seq);
-               if (!this_parent)
+               this_parent = child->d_parent;
+
+               spin_unlock(&child->d_lock);
+               spin_lock(&this_parent->d_lock);
+
+               /* might go back up the wrong parent if we have had a rename. */
+               if (!locked && read_seqretry(&rename_lock, seq))
                        goto rename_retry;
-               next = child->d_u.d_child.next;
+               next = child->d_child.next;
+               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+                       if (next == &this_parent->d_subdirs)
+                               goto ascend;
+                       child = list_entry(next, struct dentry, d_child);
+                       next = next->next;
+               }
+               rcu_read_unlock();
                goto resume;
        }
 out:
-       spin_unlock(&this_parent->d_lock);
        if (!locked && read_seqretry(&rename_lock, seq))
                goto rename_retry;
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
        if (locked)
                write_sequnlock(&rename_lock);
        return found;
 
 rename_retry:
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
        if (found)
                return found;
        if (locked)
@@ -1278,8 +1285,8 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
        INIT_HLIST_BL_NODE(&dentry->d_hash);
        INIT_LIST_HEAD(&dentry->d_lru);
        INIT_LIST_HEAD(&dentry->d_subdirs);
-       INIT_HLIST_NODE(&dentry->d_alias);
-       INIT_LIST_HEAD(&dentry->d_u.d_child);
+       INIT_HLIST_NODE(&dentry->d_u.d_alias);
+       INIT_LIST_HEAD(&dentry->d_child);
        d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
        this_cpu_inc(nr_dentry);
@@ -1309,7 +1316,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
         */
        __dget_dlock(parent);
        dentry->d_parent = parent;
-       list_add(&dentry->d_u.d_child, &parent->d_subdirs);
+       list_add(&dentry->d_child, &parent->d_subdirs);
        spin_unlock(&parent->d_lock);
 
        return dentry;
@@ -1369,7 +1376,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        if (inode) {
                if (unlikely(IS_AUTOMOUNT(inode)))
                        dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
-               hlist_add_head(&dentry->d_alias, &inode->i_dentry);
+               hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
        }
        dentry->d_inode = inode;
        dentry_rcuwalk_barrier(dentry);
@@ -1394,7 +1401,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
  
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
        if (inode)
                spin_lock(&inode->i_lock);
        __d_instantiate(entry, inode);
@@ -1433,7 +1440,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
                return NULL;
        }
 
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                /*
                 * Don't need alias->d_lock here, because aliases with
                 * d_parent == entry->d_parent are not subject to name or
@@ -1459,7 +1466,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
 {
        struct dentry *result;
 
-       BUG_ON(!hlist_unhashed(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
 
        if (inode)
                spin_lock(&inode->i_lock);
@@ -1502,7 +1509,7 @@ static struct dentry * __d_find_any_alias(struct inode *inode)
 
        if (hlist_empty(&inode->i_dentry))
                return NULL;
-       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        __dget(alias);
        return alias;
 }
@@ -1576,7 +1583,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
        spin_lock(&tmp->d_lock);
        tmp->d_inode = inode;
        tmp->d_flags |= DCACHE_DISCONNECTED;
-       hlist_add_head(&tmp->d_alias, &inode->i_dentry);
+       hlist_add_head(&tmp->d_u.d_alias, &inode->i_dentry);
        hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
        hlist_bl_unlock(&tmp->d_sb->s_anon);
@@ -2019,7 +2026,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
        struct dentry *child;
 
        spin_lock(&dparent->d_lock);
-       list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &dparent->d_subdirs, d_child) {
                if (dentry == child) {
                        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
                        __dget_dlock(dentry);
@@ -2266,8 +2273,8 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
        /* Unhash the target: dput() will then get rid of it */
        __d_drop(target);
 
-       list_del(&dentry->d_u.d_child);
-       list_del(&target->d_u.d_child);
+       list_del(&dentry->d_child);
+       list_del(&target->d_child);
 
        /* Switch the names.. */
        switch_names(dentry, target);
@@ -2277,15 +2284,15 @@ static void __d_move(struct dentry * dentry, struct dentry * target)
        if (IS_ROOT(dentry)) {
                dentry->d_parent = target->d_parent;
                target->d_parent = target;
-               INIT_LIST_HEAD(&target->d_u.d_child);
+               INIT_LIST_HEAD(&target->d_child);
        } else {
                swap(dentry->d_parent, target->d_parent);
 
                /* And add them back to the (new) parent lists */
-               list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
+               list_add(&target->d_child, &target->d_parent->d_subdirs);
        }
 
-       list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
+       list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
 
        write_seqcount_end(&target->d_seq);
        write_seqcount_end(&dentry->d_seq);
@@ -2392,9 +2399,9 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
        swap(dentry->d_name.hash, anon->d_name.hash);
 
        dentry->d_parent = dentry;
-       list_del_init(&dentry->d_u.d_child);
+       list_del_init(&dentry->d_child);
        anon->d_parent = dparent;
-       list_move(&anon->d_u.d_child, &dparent->d_subdirs);
+       list_move(&anon->d_child, &dparent->d_subdirs);
 
        write_seqcount_end(&dentry->d_seq);
        write_seqcount_end(&anon->d_seq);
@@ -2933,7 +2940,7 @@ repeat:
 resume:
        while (next != &this_parent->d_subdirs) {
                struct list_head *tmp = next;
-               struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
+               struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
                next = tmp->next;
 
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
@@ -2954,26 +2961,43 @@ resume:
                }
                spin_unlock(&dentry->d_lock);
        }
+       rcu_read_lock();
+ascend:
        if (this_parent != root) {
                struct dentry *child = this_parent;
                if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
                        this_parent->d_flags |= DCACHE_GENOCIDE;
                        this_parent->d_count--;
                }
-               this_parent = try_to_ascend(this_parent, locked, seq);
-               if (!this_parent)
+               this_parent = child->d_parent;
+
+               spin_unlock(&child->d_lock);
+               spin_lock(&this_parent->d_lock);
+
+               /* might go back up the wrong parent if we have had a rename. */
+               if (!locked && read_seqretry(&rename_lock, seq))
                        goto rename_retry;
-               next = child->d_u.d_child.next;
+               next = child->d_child.next;
+               while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
+                       if (next == &this_parent->d_subdirs)
+                               goto ascend;
+                       child = list_entry(next, struct dentry, d_child);
+                       next = next->next;
+               }
+               rcu_read_unlock();
                goto resume;
        }
-       spin_unlock(&this_parent->d_lock);
        if (!locked && read_seqretry(&rename_lock, seq))
                goto rename_retry;
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
        if (locked)
                write_sequnlock(&rename_lock);
        return;
 
 rename_retry:
+       spin_unlock(&this_parent->d_lock);
+       rcu_read_unlock();
        if (locked)
                goto again;
        locked = 1;
index 4660a419033f3485a2e306b65a1d7aa184235c1b..84378f0ffd6da46ca0f1a4d97c46184d5c10aa9e 100644 (file)
@@ -546,7 +546,7 @@ void debugfs_remove_recursive(struct dentry *dentry)
        parent = dentry;
  down:
        mutex_lock(&parent->d_inode->i_mutex);
-       list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
+       list_for_each_entry_safe(child, next, &parent->d_subdirs, d_child) {
                if (!debugfs_positive(child))
                        continue;
 
@@ -567,8 +567,8 @@ void debugfs_remove_recursive(struct dentry *dentry)
        mutex_lock(&parent->d_inode->i_mutex);
 
        if (child != dentry) {
-               next = list_entry(child->d_u.d_child.next, struct dentry,
-                                       d_u.d_child);
+               next = list_entry(child->d_child.next, struct dentry,
+                                       d_child);
                goto up;
        }
 
index 43b448ddc3dc3e479e457d75720cebb6e512e22f..dc4784b52d92cb3e5b0b98edce033b3a3f03ee9c 100644 (file)
@@ -50,7 +50,7 @@ find_acceptable_alias(struct dentry *result,
 
        inode = result->d_inode;
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                dget(dentry);
                spin_unlock(&inode->i_lock);
                if (toput)
index e6941e622d310eb1ab47793b7c2e984609cebf0b..1fefeb7d14dbe6bb62a4fbd23679ed947c40fb88 100644 (file)
@@ -655,6 +655,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 
        BUG_ON(end < lblk);
 
+       if ((status & EXTENT_STATUS_DELAYED) &&
+           (status & EXTENT_STATUS_WRITTEN)) {
+               ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as "
+                               " delayed and written which can potentially "
+                               " cause data loss.\n", lblk, len);
+               WARN_ON(1);
+       }
+
        newes.es_lblk = lblk;
        newes.es_len = len;
        ext4_es_store_pblock(&newes, pblk);
index e48bd5a1814b72dbf751b1d4390a0bae167e4cb6..8a277505a3bebb0933a07637feb605ccf9e40e37 100644 (file)
@@ -626,6 +626,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
+                   !(status & EXTENT_STATUS_WRITTEN) &&
                    ext4_find_delalloc_range(inode, map->m_lblk,
                                             map->m_lblk + map->m_len - 1))
                        status |= EXTENT_STATUS_DELAYED;
@@ -736,6 +737,7 @@ found:
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
+                   !(status & EXTENT_STATUS_WRITTEN) &&
                    ext4_find_delalloc_range(inode, map->m_lblk,
                                             map->m_lblk + map->m_len - 1))
                        status |= EXTENT_STATUS_DELAYED;
@@ -1030,7 +1032,8 @@ retry_journal:
                ext4_journal_stop(handle);
                goto retry_grab;
        }
-       wait_on_page_writeback(page);
+       /* In case writeback began while the page was unlocked */
+       wait_for_stable_page(page);
 
        if (ext4_should_dioread_nolock(inode))
                ret = __block_write_begin(page, pos, len, ext4_get_block_write);
@@ -2727,7 +2730,7 @@ retry_journal:
                goto retry_grab;
        }
        /* In case writeback began while the page was unlocked */
-       wait_on_page_writeback(page);
+       wait_for_stable_page(page);
 
        ret = __block_write_begin(page, pos, len, ext4_da_get_block_prep);
        if (ret < 0) {
index f1312173fa90a5fdd685362138d06be7b16e8597..facf8590b7141448534ba662bd7ea6f4bad29254 100644 (file)
@@ -1880,7 +1880,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                          struct inode *inode)
 {
        struct inode *dir = dentry->d_parent->d_inode;
-       struct buffer_head *bh;
+       struct buffer_head *bh = NULL;
        struct ext4_dir_entry_2 *de;
        struct ext4_dir_entry_tail *t;
        struct super_block *sb;
@@ -1905,14 +1905,14 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                        return retval;
                if (retval == 1) {
                        retval = 0;
-                       return retval;
+                       goto out;
                }
        }
 
        if (is_dx(dir)) {
                retval = ext4_dx_add_entry(handle, dentry, inode);
                if (!retval || (retval != ERR_BAD_DX_DIR))
-                       return retval;
+                       goto out;
                ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
                dx_fallback++;
                ext4_mark_inode_dirty(handle, dir);
@@ -1924,14 +1924,15 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                        return PTR_ERR(bh);
 
                retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
-               if (retval != -ENOSPC) {
-                       brelse(bh);
-                       return retval;
-               }
+               if (retval != -ENOSPC)
+                       goto out;
 
                if (blocks == 1 && !dx_fallback &&
-                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
-                       return make_indexed_dir(handle, dentry, inode, bh);
+                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
+                       retval = make_indexed_dir(handle, dentry, inode, bh);
+                       bh = NULL; /* make_indexed_dir releases bh */
+                       goto out;
+               }
                brelse(bh);
        }
        bh = ext4_append(handle, dir, &block);
@@ -1947,6 +1948,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        }
 
        retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
+out:
        brelse(bh);
        if (retval == 0)
                ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
index c450fdb3d78d21575440fb73bed5bb5e0ae911e8..5d876b1c9ea452ca8afd4daa3511e69c78adb59b 100644 (file)
@@ -3103,7 +3103,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                 * self "."
                                 */
                                filp->f_pos = 1;
-                               if (filldir(dirent, ".", 1, 0, ip->i_ino,
+                               if (filldir(dirent, ".", 1, 1, ip->i_ino,
                                            DT_DIR))
                                        return 0;
                        }
@@ -3111,7 +3111,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                         * parent ".."
                         */
                        filp->f_pos = 2;
-                       if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
+                       if (filldir(dirent, "..", 2, 2, PARENT(ip), DT_DIR))
                                return 0;
 
                        /*
index 916da8c4158b0c01d834ead4b056b014eb1797a1..1299bd5e07b7f28e431261a0c2ad138b7fd9fe74 100644 (file)
@@ -104,18 +104,18 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
 
                        spin_lock(&dentry->d_lock);
                        /* d_lock not required for cursor */
-                       list_del(&cursor->d_u.d_child);
+                       list_del(&cursor->d_child);
                        p = dentry->d_subdirs.next;
                        while (n && p != &dentry->d_subdirs) {
                                struct dentry *next;
-                               next = list_entry(p, struct dentry, d_u.d_child);
+                               next = list_entry(p, struct dentry, d_child);
                                spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
                                if (simple_positive(next))
                                        n--;
                                spin_unlock(&next->d_lock);
                                p = p->next;
                        }
-                       list_add_tail(&cursor->d_u.d_child, p);
+                       list_add_tail(&cursor->d_child, p);
                        spin_unlock(&dentry->d_lock);
                }
        }
@@ -139,7 +139,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
        struct dentry *dentry = filp->f_path.dentry;
        struct dentry *cursor = filp->private_data;
-       struct list_head *p, *q = &cursor->d_u.d_child;
+       struct list_head *p, *q = &cursor->d_child;
        ino_t ino;
        int i = filp->f_pos;
 
@@ -165,7 +165,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
 
                        for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
                                struct dentry *next;
-                               next = list_entry(p, struct dentry, d_u.d_child);
+                               next = list_entry(p, struct dentry, d_child);
                                spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
                                if (!simple_positive(next)) {
                                        spin_unlock(&next->d_lock);
@@ -289,7 +289,7 @@ int simple_empty(struct dentry *dentry)
        int ret = 0;
 
        spin_lock(&dentry->d_lock);
-       list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) {
+       list_for_each_entry(child, &dentry->d_subdirs, d_child) {
                spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
                if (simple_positive(child)) {
                        spin_unlock(&child->d_lock);
index f7c4393f853533da6a7f4fb459896e596345b131..036c21246d6aba956ff62fcacc3da8e5c5e80f37 100644 (file)
@@ -1542,7 +1542,8 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
 
        if (should_follow_link(inode, follow)) {
                if (nd->flags & LOOKUP_RCU) {
-                       if (unlikely(unlazy_walk(nd, path->dentry))) {
+                       if (unlikely(nd->path.mnt != path->mnt ||
+                                    unlazy_walk(nd, path->dentry))) {
                                err = -ECHILD;
                                goto out_err;
                        }
@@ -2824,7 +2825,8 @@ finish_lookup:
 
        if (should_follow_link(inode, !symlink_ok)) {
                if (nd->flags & LOOKUP_RCU) {
-                       if (unlikely(unlazy_walk(nd, path->dentry))) {
+                       if (unlikely(nd->path.mnt != path->mnt ||
+                                    unlazy_walk(nd, path->dentry))) {
                                error = -ECHILD;
                                goto out;
                        }
index 6792ce11f2bfc19757c0a5ac0061073a5b42a900..c578ba9949e67053fa7127f165a674b750b7b1a5 100644 (file)
@@ -391,7 +391,7 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dent = list_entry(next, struct dentry, d_u.d_child);
+               dent = list_entry(next, struct dentry, d_child);
                if ((unsigned long)dent->d_fsdata == fpos) {
                        if (dent->d_inode)
                                dget(dent);
index 32c06587351a138f34b09955802ad397c5b6a5f3..6d5e7c56c79d44ef177d9a1741b86ac457d4ff82 100644 (file)
@@ -194,7 +194,7 @@ ncp_renew_dentries(struct dentry *parent)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dentry = list_entry(next, struct dentry, d_u.d_child);
+               dentry = list_entry(next, struct dentry, d_child);
 
                if (dentry->d_fsdata == NULL)
                        ncp_age_dentry(server, dentry);
@@ -216,7 +216,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent)
        spin_lock(&parent->d_lock);
        next = parent->d_subdirs.next;
        while (next != &parent->d_subdirs) {
-               dentry = list_entry(next, struct dentry, d_u.d_child);
+               dentry = list_entry(next, struct dentry, d_child);
                dentry->d_fsdata = NULL;
                ncp_age_dentry(server, dentry);
                next = next->next;
index 44efaa8c5f78f38bda40753542740874b50c7155..0fe3ced6438c744007354c88cc2d3501ac3b829c 100644 (file)
@@ -58,7 +58,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
                 */
                spin_lock(&sb->s_root->d_inode->i_lock);
                spin_lock(&sb->s_root->d_lock);
-               hlist_del_init(&sb->s_root->d_alias);
+               hlist_del_init(&sb->s_root->d_u.d_alias);
                spin_unlock(&sb->s_root->d_lock);
                spin_unlock(&sb->s_root->d_inode->i_lock);
        }
index ecdbae19a766d914e7d68c005c14356455dc83af..090d8ce25bd1036e53c26ce46e9340ee7d0a6180 100644 (file)
@@ -388,7 +388,7 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,
        nchildren = nilfs_btree_node_get_nchildren(node);
 
        if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
-                    level > NILFS_BTREE_LEVEL_MAX ||
+                    level >= NILFS_BTREE_LEVEL_MAX ||
                     nchildren < 0 ||
                     nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) {
                pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n",
index 4bb21d67d9b1b1acde17f4031ddba4d429090e49..a3153e2d0f1f459ad583f816f4a74ed4ea9cd420 100644 (file)
@@ -63,14 +63,14 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
        spin_lock(&inode->i_lock);
        /* run all of the dentries associated with this inode.  Since this is a
         * directory, there damn well better only be one item on this list */
-       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
                struct dentry *child;
 
                /* run all of the children of the original inode and fix their
                 * d_flags to indicate parental interest (their parent is the
                 * original inode) */
                spin_lock(&alias->d_lock);
-               list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
+               list_for_each_entry(child, &alias->d_subdirs, d_child) {
                        if (!child->d_inode)
                                continue;
 
index ef999729e274ead1ed88c699ee86b8011fd5ff77..ce37013b4a593eed33c6559f46693befd7ef9c4d 100644 (file)
@@ -172,7 +172,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
        struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
                spin_lock(&dentry->d_lock);
                if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
                        trace_ocfs2_find_local_alias(dentry->d_name.len,
index 2b941113e42332b3e914f386e5318f690c69e6d6..2c119d5d04c9b342747207d8730a5813ec0fcd48 100644 (file)
@@ -729,6 +729,19 @@ lookup:
        if (tmpres) {
                spin_unlock(&dlm->spinlock);
                spin_lock(&tmpres->spinlock);
+
+               /*
+                * Right after dlm spinlock was released, dlm_thread could have
+                * purged the lockres. Check if lockres got unhashed. If so
+                * start over.
+                */
+               if (hlist_unhashed(&tmpres->hash_node)) {
+                       spin_unlock(&tmpres->spinlock);
+                       dlm_lockres_put(tmpres);
+                       tmpres = NULL;
+                       goto lookup;
+               }
+
                /* Wait on the thread that is mastering the resource */
                if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
                        __dlm_wait_on_lockres(tmpres);
index 46387e49aa469a262f083314987061046e7aad58..d0e8c0b1767f2cbdfeee995621da667fc309f0a3 100644 (file)
@@ -2372,10 +2372,14 @@ out_dio:
        /* buffered aio wouldn't have proper lock coverage today */
        BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
 
+       if (unlikely(written <= 0))
+               goto no_sync;
+
        if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
            ((file->f_flags & O_DIRECT) && !direct_io)) {
-               ret = filemap_fdatawrite_range(file->f_mapping, *ppos,
-                                              *ppos + count - 1);
+               ret = filemap_fdatawrite_range(file->f_mapping,
+                                              iocb->ki_pos - written,
+                                              iocb->ki_pos - 1);
                if (ret < 0)
                        written = ret;
 
@@ -2388,10 +2392,12 @@ out_dio:
                }
 
                if (!ret)
-                       ret = filemap_fdatawait_range(file->f_mapping, *ppos,
-                                                     *ppos + count - 1);
+                       ret = filemap_fdatawait_range(file->f_mapping,
+                                                     iocb->ki_pos - written,
+                                                     iocb->ki_pos - 1);
        }
 
+no_sync:
        /*
         * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
         * function pointer which is called when o_direct io completes so that
@@ -2453,12 +2459,14 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe,
        struct address_space *mapping = out->f_mapping;
        struct inode *inode = mapping->host;
        struct splice_desc sd = {
-               .total_len = len,
                .flags = flags,
-               .pos = *ppos,
                .u.file = out,
        };
-
+       ret = generic_write_checks(out, ppos, &len, 0);
+       if(ret)
+               return ret;
+       sd.total_len = len;
+       sd.pos = *ppos;
 
        trace_ocfs2_file_splice_write(inode, out, out->f_path.dentry,
                        (unsigned long long)OCFS2_I(inode)->ip_blkno,
index 154ebf8d7c1b5388ac81a7820712527784e5a021..0e289949213348152460cd392214f2434cced2bb 100644 (file)
@@ -1187,9 +1187,19 @@ out:
        return ret;
 }
 
+static int pagemap_open(struct inode *inode, struct file *file)
+{
+       /* do not disclose physical addresses to unprivileged
+          userspace (closes a rowhammer attack vector) */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       return 0;
+}
+
 const struct file_operations proc_pagemap_operations = {
        .llseek         = mem_lseek, /* borrow this */
        .read           = pagemap_read,
+       .open           = pagemap_open,
 };
 #endif /* CONFIG_PROC_PAGE_MONITOR */
 
index 157e474ab30347cde97360a4c94de73b5aff2164..635a1425d3708ef3e334aa947c2c8d6fbb971b00 100644 (file)
@@ -1954,8 +1954,6 @@ struct treepath var = {.path_length = ILLEGAL_PATH_ELEMENT_OFFSET, .reada = 0,}
 #define MAX_US_INT 0xffff
 
 // reiserfs version 2 has max offset 60 bits. Version 1 - 32 bit offset
-#define U32_MAX (~(__u32)0)
-
 static inline loff_t max_reiserfs_offset(struct inode *inode)
 {
        if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5)
index 4b5a5fac33832f0463320af1287b495f3857d0a3..f183f1342c0127bc1739248c5bb1a95362b2eb08 100644 (file)
@@ -1012,13 +1012,17 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
        struct address_space *mapping = out->f_mapping;
        struct inode *inode = mapping->host;
        struct splice_desc sd = {
-               .total_len = len,
                .flags = flags,
-               .pos = *ppos,
                .u.file = out,
        };
        ssize_t ret;
 
+       ret = generic_write_checks(out, ppos, &len, S_ISBLK(inode->i_mode));
+       if (ret)
+               return ret;
+       sd.total_len = len;
+       sd.pos = *ppos;
+
        pipe_lock(pipe);
 
        splice_from_pipe_begin(&sd);
index 454881e6450a4493eabf6fa5de03fd005fccc761..fcabb1597d5b094f29583ccc6bd4d2166adbc292 100644 (file)
@@ -177,7 +177,7 @@ acpi_status acpi_load_tables(void);
  */
 acpi_status acpi_reallocate_root_table(void);
 
-acpi_status acpi_find_root_pointer(acpi_size *rsdp_address);
+acpi_status acpi_find_root_pointer(acpi_physical_address *rsdp_address);
 
 acpi_status acpi_unload_table_id(acpi_owner_id id);
 
index a64adcc29ae5b5316bde21354eab5015d6fcddd5..f819e813c8ac33373d1ea7acf2d5137ce890cecd 100644 (file)
@@ -198,9 +198,29 @@ typedef int INT32;
 typedef s32 acpi_native_int;
 
 typedef u32 acpi_size;
+
+#ifdef ACPI_32BIT_PHYSICAL_ADDRESS
+
+/*
+ * OSPMs can define this to shrink the size of the structures for 32-bit
+ * none PAE environment. ASL compiler may always define this to generate
+ * 32-bit OSPM compliant tables.
+ */
 typedef u32 acpi_io_address;
 typedef u32 acpi_physical_address;
 
+#else                          /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
+/*
+ * It is reported that, after some calculations, the physical addresses can
+ * wrap over the 32-bit boundary on 32-bit PAE environment.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=87971
+ */
+typedef u64 acpi_io_address;
+typedef u64 acpi_physical_address;
+
+#endif                         /* ACPI_32BIT_PHYSICAL_ADDRESS */
+
 #define ACPI_MAX_PTR                    ACPI_UINT32_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT32_MAX
 
index ef04b36ca6ed788de2e4b8c305508a2f9d165f3f..f7db107abb043808dfa44d3c25d0bca5eea4ec2a 100644 (file)
@@ -76,6 +76,7 @@
 #define ACPI_LARGE_NAMESPACE_NODE
 #define ACPI_DATA_TABLE_DISASSEMBLY
 #define ACPI_SINGLE_THREADED
+#define ACPI_32BIT_PHYSICAL_ADDRESS
 #endif
 
 /* acpi_exec configuration. Multithreaded with full AML debugger */
index 17bccd3a4b03fdfbe4db34bcc81b6df5ba25fd4b..dd6d9b89d338bb4fa7afe117d51e738480ffa6b6 100644 (file)
@@ -550,11 +550,10 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        barrier();
 #endif
-       if (pmd_none(pmdval))
+       if (pmd_none(pmdval) || pmd_trans_huge(pmdval))
                return 1;
        if (unlikely(pmd_bad(pmdval))) {
-               if (!pmd_trans_huge(pmdval))
-                       pmd_clear_bad(pmd);
+               pmd_clear_bad(pmd);
                return 1;
        }
        return 0;
index c1a1216e29ced8ad92dac7c089991e7bf97bd2c3..87b27263f5e2c146e0099848460e2ea4ebd591bc 100644 (file)
@@ -3,6 +3,8 @@
 
 /* References to section boundaries */
 
+#include <linux/compiler.h>
+
 extern char _text[], _stext[], _etext[];
 extern char _data[], _sdata[], _edata[];
 extern char __bss_start[], __bss_stop[];
@@ -18,6 +20,8 @@ extern char __start_rodata[], __end_rodata[];
 /* Start and end of .ctors section - used for constructor calls. */
 extern char __ctors_start[], __ctors_end[];
 
+extern __visible const void __nosave_begin, __nosave_end;
+
 /* function descriptor handling (if any).  Override
  * in asm/sections.h */
 #ifndef dereference_function_descriptor
index fa1abeb45b7602a4f0c1a4098f05f63d7a075281..49c48dda162dcd6e40dc58795089a17f93702fd9 100644 (file)
@@ -170,7 +170,9 @@ enum rq_flag_bits {
        __REQ_ELVPRIV,          /* elevator private data attached */
        __REQ_FAILED,           /* set if the request failed */
        __REQ_QUIET,            /* don't worry about errors */
-       __REQ_PREEMPT,          /* set for "ide_preempt" requests */
+       __REQ_PREEMPT,          /* set for "ide_preempt" requests and also
+                                  for requests for which the SCSI "quiesce"
+                                  state must be ignored. */
        __REQ_ALLOCED,          /* request came from our alloc pool */
        __REQ_COPY_USER,        /* contains copies of user pages */
        __REQ_FLUSH_SEQ,        /* request for flush sequence */
index 0442c3d800f0f9c8a9268a93715cfe2bc18c639b..a6ef9cc267ec2cfd3940bab1d8e4f7030e31ef7b 100644 (file)
@@ -8,23 +8,6 @@
 
 #include <linux/ceph/types.h>
 
-/* This seemed to be the easiest place to define these */
-
-#define        U8_MAX  ((u8)(~0U))
-#define        U16_MAX ((u16)(~0U))
-#define        U32_MAX ((u32)(~0U))
-#define        U64_MAX ((u64)(~0ULL))
-
-#define        S8_MAX  ((s8)(U8_MAX >> 1))
-#define        S16_MAX ((s16)(U16_MAX >> 1))
-#define        S32_MAX ((s32)(U32_MAX >> 1))
-#define        S64_MAX ((s64)(U64_MAX >> 1LL))
-
-#define        S8_MIN  ((s8)(-S8_MAX - 1))
-#define        S16_MIN ((s16)(-S16_MAX - 1))
-#define        S32_MIN ((s32)(-S32_MAX - 1))
-#define        S64_MIN ((s64)(-S64_MAX - 1LL))
-
 /*
  * in all cases,
  *   void **p     pointer to position pointer
index 3bf2bc41e41c7250284c6badefa2115646f38acf..a482811399a95491383b86d6d660864d3eb77ba4 100644 (file)
@@ -120,26 +120,46 @@ enum {
                { .notifier_call = fn, .priority = pri };       \
        register_cpu_notifier(&fn##_nb);                        \
 }
+
+#define __cpu_notifier(fn, pri) {                              \
+       static struct notifier_block fn##_nb =                  \
+               { .notifier_call = fn, .priority = pri };       \
+       __register_cpu_notifier(&fn##_nb);                      \
+}
 #else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
 #define cpu_notifier(fn, pri)  do { (void)(fn); } while (0)
+#define __cpu_notifier(fn, pri)        do { (void)(fn); } while (0)
 #endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern int register_cpu_notifier(struct notifier_block *nb);
+extern int __register_cpu_notifier(struct notifier_block *nb);
 extern void unregister_cpu_notifier(struct notifier_block *nb);
+extern void __unregister_cpu_notifier(struct notifier_block *nb);
 #else
 
 #ifndef MODULE
 extern int register_cpu_notifier(struct notifier_block *nb);
+extern int __register_cpu_notifier(struct notifier_block *nb);
 #else
 static inline int register_cpu_notifier(struct notifier_block *nb)
 {
        return 0;
 }
+
+static inline int __register_cpu_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
 #endif
 
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
 }
+
+static inline void __unregister_cpu_notifier(struct notifier_block *nb)
+{
+}
 #endif
 
 int cpu_up(unsigned int cpu);
@@ -147,19 +167,32 @@ void notify_cpu_starting(unsigned int cpu);
 extern void cpu_maps_update_begin(void);
 extern void cpu_maps_update_done(void);
 
+#define cpu_notifier_register_begin    cpu_maps_update_begin
+#define cpu_notifier_register_done     cpu_maps_update_done
+
 #else  /* CONFIG_SMP */
 
 #define cpu_notifier(fn, pri)  do { (void)(fn); } while (0)
+#define __cpu_notifier(fn, pri)        do { (void)(fn); } while (0)
 
 static inline int register_cpu_notifier(struct notifier_block *nb)
 {
        return 0;
 }
 
+static inline int __register_cpu_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
 }
 
+static inline void __unregister_cpu_notifier(struct notifier_block *nb)
+{
+}
+
 static inline void cpu_maps_update_begin(void)
 {
 }
@@ -168,6 +201,14 @@ static inline void cpu_maps_update_done(void)
 {
 }
 
+static inline void cpu_notifier_register_begin(void)
+{
+}
+
+static inline void cpu_notifier_register_done(void)
+{
+}
+
 #endif /* CONFIG_SMP */
 extern struct bus_type cpu_subsys;
 
@@ -179,8 +220,11 @@ extern void put_online_cpus(void);
 extern void cpu_hotplug_disable(void);
 extern void cpu_hotplug_enable(void);
 #define hotcpu_notifier(fn, pri)       cpu_notifier(fn, pri)
+#define __hotcpu_notifier(fn, pri)     __cpu_notifier(fn, pri)
 #define register_hotcpu_notifier(nb)   register_cpu_notifier(nb)
+#define __register_hotcpu_notifier(nb) __register_cpu_notifier(nb)
 #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
+#define __unregister_hotcpu_notifier(nb)       __unregister_cpu_notifier(nb)
 void clear_tasks_mm_cpumask(int cpu);
 int cpu_down(unsigned int cpu);
 
@@ -204,9 +248,12 @@ static inline void cpu_hotplug_driver_unlock(void)
 #define cpu_hotplug_disable()  do { } while (0)
 #define cpu_hotplug_enable()   do { } while (0)
 #define hotcpu_notifier(fn, pri)       do { (void)(fn); } while (0)
+#define __hotcpu_notifier(fn, pri)     do { (void)(fn); } while (0)
 /* These aren't inline functions due to a GCC bug. */
 #define register_hotcpu_notifier(nb)   ({ (void)(nb); 0; })
+#define __register_hotcpu_notifier(nb) ({ (void)(nb); 0; })
 #define unregister_hotcpu_notifier(nb) ({ (void)(nb); })
+#define __unregister_hotcpu_notifier(nb)       ({ (void)(nb); })
 #endif         /* CONFIG_HOTPLUG_CPU */
 
 #ifdef CONFIG_PM_SLEEP_SMP
index 9be5ac960fd89ad0b2474b664677dee8c0e1c280..c1999d1fe6f8dd7deed810ed9cf18623bf10c3a6 100644 (file)
@@ -120,15 +120,15 @@ struct dentry {
        void *d_fsdata;                 /* fs-specific data */
 
        struct list_head d_lru;         /* LRU list */
+       struct list_head d_child;       /* child of parent list */
+       struct list_head d_subdirs;     /* our children */
        /*
-        * d_child and d_rcu can share memory
+        * d_alias and d_rcu can share memory
         */
        union {
-               struct list_head d_child;       /* child of parent list */
+               struct hlist_node d_alias;      /* inode alias list */
                struct rcu_head d_rcu;
        } d_u;
-       struct list_head d_subdirs;     /* our children */
-       struct hlist_node d_alias;      /* inode alias list */
 };
 
 /*
index 6de0f2c14ec0ed6f1fa0d9ede3fec2a776343fe5..f05efb1160fbdd0f241b22e85b32b3beac8c4e44 100644 (file)
@@ -11,8 +11,6 @@
 #include <linux/irqnr.h>
 #include <linux/hardirq.h>
 #include <linux/irqflags.h>
-#include <linux/smp.h>
-#include <linux/percpu.h>
 #include <linux/hrtimer.h>
 #include <linux/kref.h>
 #include <linux/workqueue.h>
@@ -488,15 +486,6 @@ extern void __raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq_irqoff(unsigned int nr);
 extern void raise_softirq(unsigned int nr);
 
-/* This is the worklist that queues up per-cpu softirq work.
- *
- * send_remote_sendirq() adds work to these lists, and
- * the softirq handler itself dequeues from them.  The queues
- * are protected by disabling local cpu interrupts and they must
- * only be accessed by the local cpu that they are for.
- */
-DECLARE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
-
 DECLARE_PER_CPU(struct task_struct *, ksoftirqd);
 
 static inline struct task_struct *this_cpu_ksoftirqd(void)
@@ -504,17 +493,6 @@ static inline struct task_struct *this_cpu_ksoftirqd(void)
        return this_cpu_read(ksoftirqd);
 }
 
-/* Try to send a softirq to a remote cpu.  If this cannot be done, the
- * work will be queued to the local cpu.
- */
-extern void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq);
-
-/* Like send_remote_softirq(), but the caller must disable local cpu interrupts
- * and compute the current cpu, passed in as 'this_cpu'.
- */
-extern void __send_remote_softirq(struct call_single_data *cp, int cpu,
-                                 int this_cpu, int softirq);
-
 /* Tasklets --- multithreaded analogue of BHs.
 
    Main feature differing them of generic softirqs: tasklet
index eabc56d0f8240519d061dbc5053f2f0379caedb0..5ff503bb94f66e4817424338fd26f570e1ba5553 100644 (file)
 #define ULLONG_MAX     (~0ULL)
 #define SIZE_MAX       (~(size_t)0)
 
+#define U8_MAX         ((u8)~0U)
+#define S8_MAX         ((s8)(U8_MAX>>1))
+#define S8_MIN         ((s8)(-S8_MAX - 1))
+#define U16_MAX                ((u16)~0U)
+#define S16_MAX                ((s16)(U16_MAX>>1))
+#define S16_MIN                ((s16)(-S16_MAX - 1))
+#define U32_MAX                ((u32)~0U)
+#define S32_MAX                ((s32)(U32_MAX>>1))
+#define S32_MIN                ((s32)(-S32_MAX - 1))
+#define U64_MAX                ((u64)~0ULL)
+#define S64_MAX                ((s64)(U64_MAX>>1))
+#define S64_MIN                ((s64)(-S64_MAX - 1))
+
 #define STACK_MAGIC    0xdeadbeef
 
 #define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
index ab40149553dc1e63a611ebc8202dd1fd6b573ef9..d06441c10e323e3cc5a2012ea9d7498ae54c25ea 100644 (file)
@@ -896,6 +896,7 @@ static inline int page_mapped(struct page *page)
 #define VM_FAULT_WRITE 0x0008  /* Special case for get_user_pages */
 #define VM_FAULT_HWPOISON 0x0010       /* Hit poisoned small page */
 #define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
+#define VM_FAULT_SIGSEGV 0x0040
 
 #define VM_FAULT_NOPAGE        0x0100  /* ->fault installed the pte, not return page */
 #define VM_FAULT_LOCKED        0x0200  /* ->fault locked the returned page */
@@ -903,8 +904,8 @@ static inline int page_mapped(struct page *page)
 
 #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
 
-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
-                        VM_FAULT_HWPOISON_LARGE)
+#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
+                        VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)
 
 /* Encode hstate index for a hwpoisoned large page */
 #define VM_FAULT_SET_HINDEX(x) ((x) << 12)
index 98755767c7b067098443397aef09ecb145f0cd3e..1108acaacfc62abb35590d3e9c2c92820c49e326 100644 (file)
@@ -458,7 +458,7 @@ struct nilfs_btree_node {
 /* level */
 #define NILFS_BTREE_LEVEL_DATA          0
 #define NILFS_BTREE_LEVEL_NODE_MIN      (NILFS_BTREE_LEVEL_DATA + 1)
-#define NILFS_BTREE_LEVEL_MAX           14
+#define NILFS_BTREE_LEVEL_MAX           14     /* Max level (exclusive) */
 
 /**
  * struct nilfs_palloc_group_desc - block group descriptor
index a0bee5a28d1a578a27829edd231968e1ff11ce1d..28bd3a898cba11b090dbe0fe6d21604ae268889c 100644 (file)
@@ -206,6 +206,32 @@ void usb_put_intf(struct usb_interface *intf);
 #define USB_MAXINTERFACES      32
 #define USB_MAXIADS            (USB_MAXINTERFACES/2)
 
+/*
+ * USB Resume Timer: Every Host controller driver should drive the resume
+ * signalling on the bus for the amount of time defined by this macro.
+ *
+ * That way we will have a 'stable' behavior among all HCDs supported by Linux.
+ *
+ * Note that the USB Specification states we should drive resume for *at least*
+ * 20 ms, but it doesn't give an upper bound. This creates two possible
+ * situations which we want to avoid:
+ *
+ * (a) sometimes an msleep(20) might expire slightly before 20 ms, which causes
+ * us to fail USB Electrical Tests, thus failing Certification
+ *
+ * (b) Some (many) devices actually need more than 20 ms of resume signalling,
+ * and while we can argue that's against the USB Specification, we don't have
+ * control over which devices a certification laboratory will be using for
+ * certification. If CertLab uses a device which was tested against Windows and
+ * that happens to have relaxed resume signalling rules, we might fall into
+ * situations where we fail interoperability and electrical tests.
+ *
+ * In order to avoid both conditions, we're using a 40 ms resume timeout, which
+ * should cope with both LPJ calibration errors and devices not following every
+ * detail of the USB Specification.
+ */
+#define USB_RESUME_TIMEOUT     40 /* ms */
+
 /**
  * struct usb_interface_cache - long-term representation of a device interface
  * @num_altsetting: number of altsettings defined.
diff --git a/include/linux/zpool.h b/include/linux/zpool.h
new file mode 100644 (file)
index 0000000..f14bd75
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * zpool memory storage api
+ *
+ * Copyright (C) 2014 Dan Streetman
+ *
+ * This is a common frontend for the zbud and zsmalloc memory
+ * storage pool implementations.  Typically, this is used to
+ * store compressed memory.
+ */
+
+#ifndef _ZPOOL_H_
+#define _ZPOOL_H_
+
+struct zpool;
+
+struct zpool_ops {
+       int (*evict)(struct zpool *pool, unsigned long handle);
+};
+
+/*
+ * Control how a handle is mapped.  It will be ignored if the
+ * implementation does not support it.  Its use is optional.
+ * Note that this does not refer to memory protection, it
+ * refers to how the memory will be copied in/out if copying
+ * is necessary during mapping; read-write is the safest as
+ * it copies the existing memory in on map, and copies the
+ * changed memory back out on unmap.  Write-only does not copy
+ * in the memory and should only be used for initialization.
+ * If in doubt, use ZPOOL_MM_DEFAULT which is read-write.
+ */
+enum zpool_mapmode {
+       ZPOOL_MM_RW, /* normal read-write mapping */
+       ZPOOL_MM_RO, /* read-only (no copy-out at unmap time) */
+       ZPOOL_MM_WO, /* write-only (no copy-in at map time) */
+
+       ZPOOL_MM_DEFAULT = ZPOOL_MM_RW
+};
+
+struct zpool *zpool_create_pool(char *type, gfp_t gfp, struct zpool_ops *ops);
+
+char *zpool_get_type(struct zpool *pool);
+
+void zpool_destroy_pool(struct zpool *pool);
+
+int zpool_malloc(struct zpool *pool, size_t size, gfp_t gfp,
+                       unsigned long *handle);
+
+void zpool_free(struct zpool *pool, unsigned long handle);
+
+int zpool_shrink(struct zpool *pool, unsigned int pages,
+                       unsigned int *reclaimed);
+
+void *zpool_map_handle(struct zpool *pool, unsigned long handle,
+                       enum zpool_mapmode mm);
+
+void zpool_unmap_handle(struct zpool *pool, unsigned long handle);
+
+u64 zpool_get_total_size(struct zpool *pool);
+
+
+/**
+ * struct zpool_driver - driver implementation for zpool
+ * @type:      name of the driver.
+ * @list:      entry in the list of zpool drivers.
+ * @create:    create a new pool.
+ * @destroy:   destroy a pool.
+ * @malloc:    allocate mem from a pool.
+ * @free:      free mem from a pool.
+ * @shrink:    shrink the pool.
+ * @map:       map a handle.
+ * @unmap:     unmap a handle.
+ * @total_size:        get total size of a pool.
+ *
+ * This is created by a zpool implementation and registered
+ * with zpool.
+ */
+struct zpool_driver {
+       char *type;
+       struct module *owner;
+       atomic_t refcount;
+       struct list_head list;
+
+       void *(*create)(gfp_t gfp, struct zpool_ops *ops);
+       void (*destroy)(void *pool);
+
+       int (*malloc)(void *pool, size_t size, gfp_t gfp,
+                               unsigned long *handle);
+       void (*free)(void *pool, unsigned long handle);
+
+       int (*shrink)(void *pool, unsigned int pages,
+                               unsigned int *reclaimed);
+
+       void *(*map)(void *pool, unsigned long handle,
+                               enum zpool_mapmode mm);
+       void (*unmap)(void *pool, unsigned long handle);
+
+       u64 (*total_size)(void *pool);
+};
+
+void zpool_register_driver(struct zpool_driver *driver);
+
+int zpool_unregister_driver(struct zpool_driver *driver);
+
+int zpool_evict(void *pool, unsigned long handle);
+
+#endif
diff --git a/include/linux/zsmalloc.h b/include/linux/zsmalloc.h
new file mode 100644 (file)
index 0000000..ebb2841
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * zsmalloc memory allocator
+ *
+ * Copyright (C) 2011  Nitin Gupta
+ * Copyright (C) 2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the license that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ */
+
+#ifndef _ZS_MALLOC_H_
+#define _ZS_MALLOC_H_
+
+#include <linux/types.h>
+
+/*
+ * zsmalloc mapping modes
+ *
+ * NOTE: These only make a difference when a mapped object spans pages
+*/
+enum zs_mapmode {
+       ZS_MM_RW, /* normal read-write mapping */
+       ZS_MM_RO, /* read-only (no copy-out at unmap time) */
+       ZS_MM_WO /* write-only (no copy-in at map time) */
+};
+
+struct zs_pool;
+
+struct zs_pool *zs_create_pool(gfp_t flags);
+void zs_destroy_pool(struct zs_pool *pool);
+
+unsigned long zs_malloc(struct zs_pool *pool, size_t size);
+void zs_free(struct zs_pool *pool, unsigned long obj);
+
+void *zs_map_object(struct zs_pool *pool, unsigned long handle,
+                       enum zs_mapmode mm);
+void zs_unmap_object(struct zs_pool *pool, unsigned long handle);
+
+unsigned long zs_get_total_pages(struct zs_pool *pool);
+
+#endif
index dfb42ca6d0436539ada89bcd063c26e5c4e85d86..8898cdeb42a4a85a3025c8238ad5dfc775265f74 100644 (file)
@@ -41,7 +41,8 @@
 
 #define EMUPAGESIZE     4096
 #define MAXREQVOICES    8
-#define MAXPAGES        8192
+#define MAXPAGES0       4096   /* 32 bit mode */
+#define MAXPAGES1       8192   /* 31 bit mode */
 #define RESERVED        0
 #define NUM_MIDI        16
 #define NUM_G           64              /* use all channels */
@@ -50,8 +51,7 @@
 
 /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */
 #define EMU10K1_DMA_MASK       0x7fffffffUL    /* 31bit */
-#define AUDIGY_DMA_MASK                0x7fffffffUL    /* 31bit FIXME - 32 should work? */
-                                               /* See ALSA bug #1276 - rlrevell */
+#define AUDIGY_DMA_MASK                0xffffffffUL    /* 32bit mode */
 
 #define TMEMSIZE        256*1024
 #define TMEMSIZEREG     4
 
 #define MAPB                   0x0d            /* Cache map B                                          */
 
-#define MAP_PTE_MASK           0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
-#define MAP_PTI_MASK           0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
+#define MAP_PTE_MASK0          0xfffff000      /* The 20 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK0          0x00000fff      /* The 12 bit index to one of the 4096 PTE dwords       */
+
+#define MAP_PTE_MASK1          0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK1          0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
 
 /* 0x0e, 0x0f: Not used */
 
@@ -1706,6 +1709,7 @@ struct snd_emu10k1 {
        unsigned short model;                   /* subsystem id */
        unsigned int card_type;                 /* EMU10K1_CARD_* */
        unsigned int ecard_ctrl;                /* ecard control bits */
+       unsigned int address_mode;              /* address mode */
        unsigned long dma_mask;                 /* PCI DMA mask */
        unsigned int delay_pcm_irq;             /* in samples */
        int max_cache_pages;                    /* max memory size / PAGE_SIZE */
index 892f6585dd6014a7b1fb70cabd8f7ce0d2f9a4ad..d3b376025e9b86bfcdda9fe9af937f55809d487b 100644 (file)
@@ -381,7 +381,7 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
                        uptr = compat_ptr(ipck.msgp);
                        fifth = ipck.msgtyp;
                }
-               return do_msgrcv(first, uptr, second, fifth, third,
+               return do_msgrcv(first, uptr, second, (s32)fifth, third,
                                 compat_do_msg_fill);
        }
        case MSGGET:
index e646e870ec5fbe6929e582866c313cd513a5ac0b..fcf0aeff45b47b545a8155adcd583d3c1ff3b5dc 100644 (file)
@@ -984,7 +984,7 @@ static void cgroup_d_remove_dir(struct dentry *dentry)
        parent = dentry->d_parent;
        spin_lock(&parent->d_lock);
        spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-       list_del_init(&dentry->d_u.d_child);
+       list_del_init(&dentry->d_child);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&parent->d_lock);
        remove_dir(dentry);
index 7d4755634d32c38b55e86944283a49bdebf5ec97..f1cfa7367a9281e17cee3bc61541b72cee309b23 100644 (file)
 static DEFINE_MUTEX(cpu_add_remove_lock);
 
 /*
- * The following two API's must be used when attempting
- * to serialize the updates to cpu_online_mask, cpu_present_mask.
+ * The following two APIs (cpu_maps_update_begin/done) must be used when
+ * attempting to serialize the updates to cpu_online_mask & cpu_present_mask.
+ * The APIs cpu_notifier_register_begin/done() must be used to protect CPU
+ * hotplug callback (un)registration performed using __register_cpu_notifier()
+ * or __unregister_cpu_notifier().
  */
 void cpu_maps_update_begin(void)
 {
        mutex_lock(&cpu_add_remove_lock);
 }
+EXPORT_SYMBOL(cpu_notifier_register_begin);
 
 void cpu_maps_update_done(void)
 {
        mutex_unlock(&cpu_add_remove_lock);
 }
+EXPORT_SYMBOL(cpu_notifier_register_done);
 
 static RAW_NOTIFIER_HEAD(cpu_chain);
 
@@ -169,6 +174,11 @@ int __ref register_cpu_notifier(struct notifier_block *nb)
        return ret;
 }
 
+int __ref __register_cpu_notifier(struct notifier_block *nb)
+{
+       return raw_notifier_chain_register(&cpu_chain, nb);
+}
+
 static int __cpu_notify(unsigned long val, void *v, int nr_to_call,
                        int *nr_calls)
 {
@@ -192,6 +202,7 @@ static void cpu_notify_nofail(unsigned long val, void *v)
        BUG_ON(cpu_notify(val, v));
 }
 EXPORT_SYMBOL(register_cpu_notifier);
+EXPORT_SYMBOL(__register_cpu_notifier);
 
 void __ref unregister_cpu_notifier(struct notifier_block *nb)
 {
@@ -201,6 +212,12 @@ void __ref unregister_cpu_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+void __ref __unregister_cpu_notifier(struct notifier_block *nb)
+{
+       raw_notifier_chain_unregister(&cpu_chain, nb);
+}
+EXPORT_SYMBOL(__unregister_cpu_notifier);
+
 /**
  * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
  * @cpu: a CPU id
index 832b6a663e8a421121325e87376c086d8a7538ef..7d9dc9ad97f653ec084e33346564cf0b213a81c9 100644 (file)
@@ -111,7 +111,7 @@ static struct console *exclusive_console;
  */
 struct console_cmdline
 {
-       char    name[8];                        /* Name of the driver       */
+       char    name[16];                       /* Name of the driver       */
        int     index;                          /* Minor dev. to use        */
        char    *options;                       /* Options for the driver   */
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
@@ -2314,6 +2314,8 @@ void register_console(struct console *newcon)
         */
        for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
                        i++) {
+               BUILD_BUG_ON(sizeof(console_cmdline[i].name) !=
+                            sizeof(newcon->name));
                if (strcmp(console_cmdline[i].name, newcon->name) != 0)
                        continue;
                if (newcon->index >= 0 &&
index afadcf7b4a22ddcdfd5b26993f892d8dd0eae653..118323bc852982de01c839b4bcbe32e22fbe4105 100644 (file)
@@ -720,6 +720,8 @@ static int ptrace_peek_siginfo(struct task_struct *child,
 static int ptrace_resume(struct task_struct *child, long request,
                         unsigned long data)
 {
+       bool need_siglock;
+
        if (!valid_signal(data))
                return -EIO;
 
@@ -747,8 +749,26 @@ static int ptrace_resume(struct task_struct *child, long request,
                user_disable_single_step(child);
        }
 
+       /*
+        * Change ->exit_code and ->state under siglock to avoid the race
+        * with wait_task_stopped() in between; a non-zero ->exit_code will
+        * wrongly look like another report from tracee.
+        *
+        * Note that we need siglock even if ->exit_code == data and/or this
+        * status was not reported yet, the new status must not be cleared by
+        * wait_task_stopped() after resume.
+        *
+        * If data == 0 we do not care if wait_task_stopped() reports the old
+        * status and clears the code too; this can't race with the tracee, it
+        * takes siglock after resume.
+        */
+       need_siglock = data && !thread_group_empty(current);
+       if (need_siglock)
+               spin_lock_irq(&child->sighand->siglock);
        child->exit_code = data;
        wake_up_state(child, __TASK_TRACED);
+       if (need_siglock)
+               spin_unlock_irq(&child->sighand->siglock);
 
        return 0;
 }
index 787b3a032429a7a88321caf473f6f0e75d12da87..b538df367de360b85a67051dc03208908154fe5c 100644 (file)
@@ -6,8 +6,6 @@
  *     Distribute under GPLv2.
  *
  *     Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903)
- *
- *     Remote softirq infrastructure is by Jens Axboe.
  */
 
 #include <linux/export.h>
@@ -620,146 +618,17 @@ void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
 }
 EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
 
-/*
- * Remote softirq bits
- */
-
-DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
-EXPORT_PER_CPU_SYMBOL(softirq_work_list);
-
-static void __local_trigger(struct call_single_data *cp, int softirq)
-{
-       struct list_head *head = &__get_cpu_var(softirq_work_list[softirq]);
-
-       list_add_tail(&cp->list, head);
-
-       /* Trigger the softirq only if the list was previously empty.  */
-       if (head->next == &cp->list)
-               raise_softirq_irqoff(softirq);
-}
-
-#ifdef CONFIG_USE_GENERIC_SMP_HELPERS
-static void remote_softirq_receive(void *data)
-{
-       struct call_single_data *cp = data;
-       unsigned long flags;
-       int softirq;
-
-       softirq = *(int *)cp->info;
-       local_irq_save(flags);
-       __local_trigger(cp, softirq);
-       local_irq_restore(flags);
-}
-
-static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
-{
-       if (cpu_online(cpu)) {
-               cp->func = remote_softirq_receive;
-               cp->info = &softirq;
-               cp->flags = 0;
-
-               __smp_call_function_single(cpu, cp, 0);
-               return 0;
-       }
-       return 1;
-}
-#else /* CONFIG_USE_GENERIC_SMP_HELPERS */
-static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
-{
-       return 1;
-}
-#endif
-
-/**
- * __send_remote_softirq - try to schedule softirq work on a remote cpu
- * @cp: private SMP call function data area
- * @cpu: the remote cpu
- * @this_cpu: the currently executing cpu
- * @softirq: the softirq for the work
- *
- * Attempt to schedule softirq work on a remote cpu.  If this cannot be
- * done, the work is instead queued up on the local cpu.
- *
- * Interrupts must be disabled.
- */
-void __send_remote_softirq(struct call_single_data *cp, int cpu, int this_cpu, int softirq)
-{
-       if (cpu == this_cpu || __try_remote_softirq(cp, cpu, softirq))
-               __local_trigger(cp, softirq);
-}
-EXPORT_SYMBOL(__send_remote_softirq);
-
-/**
- * send_remote_softirq - try to schedule softirq work on a remote cpu
- * @cp: private SMP call function data area
- * @cpu: the remote cpu
- * @softirq: the softirq for the work
- *
- * Like __send_remote_softirq except that disabling interrupts and
- * computing the current cpu is done for the caller.
- */
-void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
-{
-       unsigned long flags;
-       int this_cpu;
-
-       local_irq_save(flags);
-       this_cpu = smp_processor_id();
-       __send_remote_softirq(cp, cpu, this_cpu, softirq);
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(send_remote_softirq);
-
-static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self,
-                                              unsigned long action, void *hcpu)
-{
-       /*
-        * If a CPU goes away, splice its entries to the current CPU
-        * and trigger a run of the softirq
-        */
-       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
-               int cpu = (unsigned long) hcpu;
-               int i;
-
-               local_irq_disable();
-               for (i = 0; i < NR_SOFTIRQS; i++) {
-                       struct list_head *head = &per_cpu(softirq_work_list[i], cpu);
-                       struct list_head *local_head;
-
-                       if (list_empty(head))
-                               continue;
-
-                       local_head = &__get_cpu_var(softirq_work_list[i]);
-                       list_splice_init(head, local_head);
-                       raise_softirq_irqoff(i);
-               }
-               local_irq_enable();
-       }
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block __cpuinitdata remote_softirq_cpu_notifier = {
-       .notifier_call  = remote_softirq_cpu_notify,
-};
-
 void __init softirq_init(void)
 {
        int cpu;
 
        for_each_possible_cpu(cpu) {
-               int i;
-
                per_cpu(tasklet_vec, cpu).tail =
                        &per_cpu(tasklet_vec, cpu).head;
                per_cpu(tasklet_hi_vec, cpu).tail =
                        &per_cpu(tasklet_hi_vec, cpu).head;
-               for (i = 0; i < NR_SOFTIRQS; i++)
-                       INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
        }
 
-       register_hotcpu_notifier(&remote_softirq_cpu_notifier);
-
        open_softirq(TASKLET_SOFTIRQ, tasklet_action);
        open_softirq(HI_SOFTIRQ, tasklet_hi_action);
 }
@@ -774,9 +643,13 @@ static void run_ksoftirqd(unsigned int cpu)
        local_irq_disable();
        if (local_softirq_pending()) {
                __do_softirq();
-               rcu_note_context_switch(cpu);
                local_irq_enable();
                cond_resched();
+
+               preempt_disable();
+               rcu_note_context_switch(cpu);
+               preempt_enable();
+
                return;
        }
        local_irq_enable();
index 3d9fee3a80b39fb4867fcb861298094442fff518..ab21b8c665354a28656058b447ac8859a7c0cf37 100644 (file)
@@ -2650,7 +2650,7 @@ static DEFINE_PER_CPU(unsigned int, current_context);
 
 static __always_inline int trace_recursive_lock(void)
 {
-       unsigned int val = this_cpu_read(current_context);
+       unsigned int val = __this_cpu_read(current_context);
        int bit;
 
        if (in_interrupt()) {
@@ -2667,18 +2667,17 @@ static __always_inline int trace_recursive_lock(void)
                return 1;
 
        val |= (1 << bit);
-       this_cpu_write(current_context, val);
+       __this_cpu_write(current_context, val);
 
        return 0;
 }
 
 static __always_inline void trace_recursive_unlock(void)
 {
-       unsigned int val = this_cpu_read(current_context);
+       unsigned int val = __this_cpu_read(current_context);
 
-       val--;
-       val &= this_cpu_read(current_context);
-       this_cpu_write(current_context, val);
+       val &= val & (val - 1);
+       __this_cpu_write(current_context, val);
 }
 
 #else
index 88e8f9057d1a7ae63eab67860084db21ee4409dc..249e32b5aa0dd973693482c14b1c3d7c554ed1db 100644 (file)
@@ -6154,7 +6154,7 @@ static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t m
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
@@ -6181,7 +6181,7 @@ static int instance_rmdir(struct inode *inode, struct dentry *dentry)
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
index 001b349af9398a14e8ae392962e22cc43970b738..5a898f15bfc6ea4aff291fdad3de8ad2f654224b 100644 (file)
@@ -425,7 +425,7 @@ static void remove_event_file_dir(struct ftrace_event_file *file)
 
        if (dir) {
                spin_lock(&dir->d_lock);        /* probably unneeded */
-               list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
+               list_for_each_entry(child, &dir->d_subdirs, d_child) {
                        if (child->d_inode)     /* probably unneeded */
                                child->d_inode->i_private = NULL;
                }
index 43d0781daf4703d94be9fd988bd6054f49cdeca4..cb9ea218155780cc6ba2dab7676f72f6c4ff17a0 100644 (file)
@@ -598,7 +598,7 @@ EXPORT_SYMBOL(memset);
 void memzero_explicit(void *s, size_t count)
 {
        memset(s, 0, count);
-       OPTIMIZER_HIDE_VAR(s);
+       barrier();
 }
 EXPORT_SYMBOL(memzero_explicit);
 
index b2d1aed56439f98b74fedb9b3e81c9cedb947b1e..7c13c134f646e1a5eed45fbb3aade97a38ade583 100644 (file)
@@ -504,3 +504,35 @@ config CMA_DEBUG
          messages for every CMA call as well as various messages while
          processing calls such as dma_alloc_from_contiguous().
          This option does not affect warning and error messages.
+
+config ZPOOL
+       tristate "Common API for compressed memory storage"
+       default n
+       help
+         Compressed memory storage API.  This allows using either zbud or
+         zsmalloc.
+
+config ZSMALLOC
+       bool "Memory allocator for compressed pages"
+       depends on MMU
+       default n
+       help
+         zsmalloc is a slab-based memory allocator designed to store
+         compressed RAM pages.  zsmalloc uses virtual memory mapping
+         in order to reduce fragmentation.  However, this results in a
+         non-standard allocator interface where a handle, not a pointer, is
+         returned by an alloc().  This handle must be mapped in order to
+         access the allocated space.
+
+config PGTABLE_MAPPING
+       bool "Use page table mapping to access object in zsmalloc"
+       depends on ZSMALLOC
+       help
+         By default, zsmalloc uses a copy-based object mapping method to
+         access allocations that span two pages. However, if a particular
+         architecture (ex, ARM) performs VM mapping faster than copying,
+         then you should select this. This causes zsmalloc to use page table
+         mapping rather than copying for object mapping.
+
+         You can check speed with zsmalloc benchmark[1].
+         [1] https://github.com/spartacus06/zsmalloc
index 89244cb96221a3cb78d51b07b0fbc45c041dd091..0fa6442b4d4cf5719eaf57ce5c1f33ca39f22d1d 100644 (file)
@@ -59,3 +59,5 @@ obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
 obj-$(CONFIG_CLEANCACHE) += cleancache.o
 obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o
 obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o
+obj-$(CONFIG_ZPOOL)    += zpool.o
+obj-$(CONFIG_ZSMALLOC) += zsmalloc.o
index 784d1e4bc3852ef0598708263ad39aaa01f46885..7bf748f30aab4f05c9828b6a98ee3400b96515e0 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -376,7 +376,7 @@ static int break_ksm(struct vm_area_struct *vma, unsigned long addr)
                else
                        ret = VM_FAULT_WRITE;
                put_page(page);
-       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM)));
+       } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM)));
        /*
         * We must loop because handle_mm_fault() may back out if there's
         * any difficulty e.g. if pte accessed bit gets updated concurrently.
index 603f1fa1b7a3aaffc6b1f198ef62e8a4f1391e73..ca96f411b0346c15f26f3919bfdf53f9b2012880 100644 (file)
@@ -1117,10 +1117,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
         * The check (unnecessarily) ignores LRU pages being isolated and
         * walked by the page reclaim code, however that's not a big loss.
         */
-       if (!PageHuge(p) && !PageTransTail(p)) {
-               if (!PageLRU(p))
-                       shake_page(p, 0);
-               if (!PageLRU(p)) {
+       if (!PageHuge(p)) {
+               if (!PageLRU(hpage))
+                       shake_page(hpage, 0);
+               if (!PageLRU(hpage)) {
                        /*
                         * shake_page could have turned it free.
                         */
index 280930f51ef61877bbabc033b176bc1441b70766..7c86434d9cfeebdea0e7ed0eee12c2942fa6e10f 100644 (file)
@@ -1846,7 +1846,8 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                                else
                                                        return -EFAULT;
                                        }
-                                       if (ret & VM_FAULT_SIGBUS)
+                                       if (ret & (VM_FAULT_SIGBUS |
+                                                  VM_FAULT_SIGSEGV))
                                                return i ? i : -EFAULT;
                                        BUG();
                                }
@@ -1956,7 +1957,7 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
                        return -ENOMEM;
                if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
                        return -EHWPOISON;
-               if (ret & VM_FAULT_SIGBUS)
+               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
                        return -EFAULT;
                BUG();
        }
@@ -3233,7 +3234,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
 
        /* Check if we need to add a guard page to the stack */
        if (check_stack_guard_page(vma, address) < 0)
-               return VM_FAULT_SIGBUS;
+               return VM_FAULT_SIGSEGV;
 
        /* Use the zero-page for reads */
        if (!(flags & FAULT_FLAG_WRITE)) {
index 1ad92b46753edfe8d9f54fae81c5f3aa15b34110..2298237db1429a464c064241a77ada2f61e7552d 100644 (file)
@@ -1039,6 +1039,10 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
                        return NULL;
 
                arch_refresh_nodedata(nid, pgdat);
+       } else {
+               /* Reset the nr_zones and classzone_idx to 0 before reuse */
+               pgdat->nr_zones = 0;
+               pgdat->classzone_idx = 0;
        }
 
        /* we can use NODE_DATA(nid) from here */
@@ -1802,15 +1806,6 @@ void try_offline_node(int nid)
                if (is_vmalloc_addr(zone->wait_table))
                        vfree(zone->wait_table);
        }
-
-       /*
-        * Since there is no way to guarentee the address of pgdat/zone is not
-        * on stack of any kernel threads or used by other kernel objects
-        * without reference counting or other symchronizing method, do not
-        * reset node_data and free pgdat here. Just reset it to 0 and reuse
-        * the memory when the node is online again.
-        */
-       memset(pgdat, 0, sizeof(*pgdat));
 }
 EXPORT_SYMBOL(try_offline_node);
 
index 5a45b9d0acd4650f908adaed20e40cbde21548b1..cdbe3cd0f86d9e679329ae9b6f1b42ab3f38d6e6 100644 (file)
@@ -794,8 +794,11 @@ static void bdi_update_write_bandwidth(struct backing_dev_info *bdi,
         *                   bw * elapsed + write_bandwidth * (period - elapsed)
         * write_bandwidth = ---------------------------------------------------
         *                                          period
+        *
+        * @written may have decreased due to account_page_redirty().
+        * Avoid underflowing @bw calculation.
         */
-       bw = written - bdi->written_stamp;
+       bw = written - min(written, bdi->written_stamp);
        bw *= HZ;
        if (unlikely(elapsed > period)) {
                do_div(bw, elapsed);
@@ -859,7 +862,7 @@ static void global_update_bandwidth(unsigned long thresh,
                                    unsigned long now)
 {
        static DEFINE_SPINLOCK(dirty_lock);
-       static unsigned long update_time;
+       static unsigned long update_time = INITIAL_JIFFIES;
 
        /*
         * check locklessly first to optimize away locking for the most time
diff --git a/mm/zpool.c b/mm/zpool.c
new file mode 100644 (file)
index 0000000..739cdf0
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * zpool memory storage api
+ *
+ * Copyright (C) 2014 Dan Streetman
+ *
+ * This is a common frontend for memory storage pool implementations.
+ * Typically, this is used to store compressed memory.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/zpool.h>
+
+struct zpool {
+       char *type;
+
+       struct zpool_driver *driver;
+       void *pool;
+       struct zpool_ops *ops;
+
+       struct list_head list;
+};
+
+static LIST_HEAD(drivers_head);
+static DEFINE_SPINLOCK(drivers_lock);
+
+static LIST_HEAD(pools_head);
+static DEFINE_SPINLOCK(pools_lock);
+
+/**
+ * zpool_register_driver() - register a zpool implementation.
+ * @driver:    driver to register
+ */
+void zpool_register_driver(struct zpool_driver *driver)
+{
+       spin_lock(&drivers_lock);
+       atomic_set(&driver->refcount, 0);
+       list_add(&driver->list, &drivers_head);
+       spin_unlock(&drivers_lock);
+}
+EXPORT_SYMBOL(zpool_register_driver);
+
+/**
+ * zpool_unregister_driver() - unregister a zpool implementation.
+ * @driver:    driver to unregister.
+ *
+ * Module usage counting is used to prevent using a driver
+ * while/after unloading, so if this is called from module
+ * exit function, this should never fail; if called from
+ * other than the module exit function, and this returns
+ * failure, the driver is in use and must remain available.
+ */
+int zpool_unregister_driver(struct zpool_driver *driver)
+{
+       int ret = 0, refcount;
+
+       spin_lock(&drivers_lock);
+       refcount = atomic_read(&driver->refcount);
+       WARN_ON(refcount < 0);
+       if (refcount > 0)
+               ret = -EBUSY;
+       else
+               list_del(&driver->list);
+       spin_unlock(&drivers_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(zpool_unregister_driver);
+
+/**
+ * zpool_evict() - evict callback from a zpool implementation.
+ * @pool:      pool to evict from.
+ * @handle:    handle to evict.
+ *
+ * This can be used by zpool implementations to call the
+ * user's evict zpool_ops struct evict callback.
+ */
+int zpool_evict(void *pool, unsigned long handle)
+{
+       struct zpool *zpool;
+
+       spin_lock(&pools_lock);
+       list_for_each_entry(zpool, &pools_head, list) {
+               if (zpool->pool == pool) {
+                       spin_unlock(&pools_lock);
+                       if (!zpool->ops || !zpool->ops->evict)
+                               return -EINVAL;
+                       return zpool->ops->evict(zpool, handle);
+               }
+       }
+       spin_unlock(&pools_lock);
+
+       return -ENOENT;
+}
+EXPORT_SYMBOL(zpool_evict);
+
+static struct zpool_driver *zpool_get_driver(char *type)
+{
+       struct zpool_driver *driver;
+
+       spin_lock(&drivers_lock);
+       list_for_each_entry(driver, &drivers_head, list) {
+               if (!strcmp(driver->type, type)) {
+                       bool got = try_module_get(driver->owner);
+
+                       if (got)
+                               atomic_inc(&driver->refcount);
+                       spin_unlock(&drivers_lock);
+                       return got ? driver : NULL;
+               }
+       }
+
+       spin_unlock(&drivers_lock);
+       return NULL;
+}
+
+static void zpool_put_driver(struct zpool_driver *driver)
+{
+       atomic_dec(&driver->refcount);
+       module_put(driver->owner);
+}
+
+/**
+ * zpool_create_pool() - Create a new zpool
+ * @type       The type of the zpool to create (e.g. zbud, zsmalloc)
+ * @gfp                The GFP flags to use when allocating the pool.
+ * @ops                The optional ops callback.
+ *
+ * This creates a new zpool of the specified type.  The gfp flags will be
+ * used when allocating memory, if the implementation supports it.  If the
+ * ops param is NULL, then the created zpool will not be shrinkable.
+ *
+ * Implementations must guarantee this to be thread-safe.
+ *
+ * Returns: New zpool on success, NULL on failure.
+ */
+struct zpool *zpool_create_pool(char *type, gfp_t gfp, struct zpool_ops *ops)
+{
+       struct zpool_driver *driver;
+       struct zpool *zpool;
+
+       pr_info("creating pool type %s\n", type);
+
+       driver = zpool_get_driver(type);
+
+       if (!driver) {
+               request_module("zpool-%s", type);
+               driver = zpool_get_driver(type);
+       }
+
+       if (!driver) {
+               pr_err("no driver for type %s\n", type);
+               return NULL;
+       }
+
+       zpool = kmalloc(sizeof(*zpool), gfp);
+       if (!zpool) {
+               pr_err("couldn't create zpool - out of memory\n");
+               zpool_put_driver(driver);
+               return NULL;
+       }
+
+       zpool->type = driver->type;
+       zpool->driver = driver;
+       zpool->pool = driver->create(gfp, ops);
+       zpool->ops = ops;
+
+       if (!zpool->pool) {
+               pr_err("couldn't create %s pool\n", type);
+               zpool_put_driver(driver);
+               kfree(zpool);
+               return NULL;
+       }
+
+       pr_info("created %s pool\n", type);
+
+       spin_lock(&pools_lock);
+       list_add(&zpool->list, &pools_head);
+       spin_unlock(&pools_lock);
+
+       return zpool;
+}
+
+/**
+ * zpool_destroy_pool() - Destroy a zpool
+ * @pool       The zpool to destroy.
+ *
+ * Implementations must guarantee this to be thread-safe,
+ * however only when destroying different pools.  The same
+ * pool should only be destroyed once, and should not be used
+ * after it is destroyed.
+ *
+ * This destroys an existing zpool.  The zpool should not be in use.
+ */
+void zpool_destroy_pool(struct zpool *zpool)
+{
+       pr_info("destroying pool type %s\n", zpool->type);
+
+       spin_lock(&pools_lock);
+       list_del(&zpool->list);
+       spin_unlock(&pools_lock);
+       zpool->driver->destroy(zpool->pool);
+       zpool_put_driver(zpool->driver);
+       kfree(zpool);
+}
+
+/**
+ * zpool_get_type() - Get the type of the zpool
+ * @pool       The zpool to check
+ *
+ * This returns the type of the pool.
+ *
+ * Implementations must guarantee this to be thread-safe.
+ *
+ * Returns: The type of zpool.
+ */
+char *zpool_get_type(struct zpool *zpool)
+{
+       return zpool->type;
+}
+
+/**
+ * zpool_malloc() - Allocate memory
+ * @pool       The zpool to allocate from.
+ * @size       The amount of memory to allocate.
+ * @gfp                The GFP flags to use when allocating memory.
+ * @handle     Pointer to the handle to set
+ *
+ * This allocates the requested amount of memory from the pool.
+ * The gfp flags will be used when allocating memory, if the
+ * implementation supports it.  The provided @handle will be
+ * set to the allocated object handle.
+ *
+ * Implementations must guarantee this to be thread-safe.
+ *
+ * Returns: 0 on success, negative value on error.
+ */
+int zpool_malloc(struct zpool *zpool, size_t size, gfp_t gfp,
+                       unsigned long *handle)
+{
+       return zpool->driver->malloc(zpool->pool, size, gfp, handle);
+}
+
+/**
+ * zpool_free() - Free previously allocated memory
+ * @pool       The zpool that allocated the memory.
+ * @handle     The handle to the memory to free.
+ *
+ * This frees previously allocated memory.  This does not guarantee
+ * that the pool will actually free memory, only that the memory
+ * in the pool will become available for use by the pool.
+ *
+ * Implementations must guarantee this to be thread-safe,
+ * however only when freeing different handles.  The same
+ * handle should only be freed once, and should not be used
+ * after freeing.
+ */
+void zpool_free(struct zpool *zpool, unsigned long handle)
+{
+       zpool->driver->free(zpool->pool, handle);
+}
+
+/**
+ * zpool_shrink() - Shrink the pool size
+ * @pool       The zpool to shrink.
+ * @pages      The number of pages to shrink the pool.
+ * @reclaimed  The number of pages successfully evicted.
+ *
+ * This attempts to shrink the actual memory size of the pool
+ * by evicting currently used handle(s).  If the pool was
+ * created with no zpool_ops, or the evict call fails for any
+ * of the handles, this will fail.  If non-NULL, the @reclaimed
+ * parameter will be set to the number of pages reclaimed,
+ * which may be more than the number of pages requested.
+ *
+ * Implementations must guarantee this to be thread-safe.
+ *
+ * Returns: 0 on success, negative value on error/failure.
+ */
+int zpool_shrink(struct zpool *zpool, unsigned int pages,
+                       unsigned int *reclaimed)
+{
+       return zpool->driver->shrink(zpool->pool, pages, reclaimed);
+}
+
+/**
+ * zpool_map_handle() - Map a previously allocated handle into memory
+ * @pool       The zpool that the handle was allocated from
+ * @handle     The handle to map
+ * @mm         How the memory should be mapped
+ *
+ * This maps a previously allocated handle into memory.  The @mm
+ * param indicates to the implementation how the memory will be
+ * used, i.e. read-only, write-only, read-write.  If the
+ * implementation does not support it, the memory will be treated
+ * as read-write.
+ *
+ * This may hold locks, disable interrupts, and/or preemption,
+ * and the zpool_unmap_handle() must be called to undo those
+ * actions.  The code that uses the mapped handle should complete
+ * its operatons on the mapped handle memory quickly and unmap
+ * as soon as possible.  As the implementation may use per-cpu
+ * data, multiple handles should not be mapped concurrently on
+ * any cpu.
+ *
+ * Returns: A pointer to the handle's mapped memory area.
+ */
+void *zpool_map_handle(struct zpool *zpool, unsigned long handle,
+                       enum zpool_mapmode mapmode)
+{
+       return zpool->driver->map(zpool->pool, handle, mapmode);
+}
+
+/**
+ * zpool_unmap_handle() - Unmap a previously mapped handle
+ * @pool       The zpool that the handle was allocated from
+ * @handle     The handle to unmap
+ *
+ * This unmaps a previously mapped handle.  Any locks or other
+ * actions that the implementation took in zpool_map_handle()
+ * will be undone here.  The memory area returned from
+ * zpool_map_handle() should no longer be used after this.
+ */
+void zpool_unmap_handle(struct zpool *zpool, unsigned long handle)
+{
+       zpool->driver->unmap(zpool->pool, handle);
+}
+
+/**
+ * zpool_get_total_size() - The total size of the pool
+ * @pool       The zpool to check
+ *
+ * This returns the total size in bytes of the pool.
+ *
+ * Returns: Total size of the zpool in bytes.
+ */
+u64 zpool_get_total_size(struct zpool *zpool)
+{
+       return zpool->driver->total_size(zpool->pool);
+}
+
+static int __init init_zpool(void)
+{
+       pr_info("loaded\n");
+       return 0;
+}
+
+static void __exit exit_zpool(void)
+{
+       pr_info("unloaded\n");
+}
+
+module_init(init_zpool);
+module_exit(exit_zpool);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>");
+MODULE_DESCRIPTION("Common API for compressed memory storage");
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
new file mode 100644 (file)
index 0000000..7031e12
--- /dev/null
@@ -0,0 +1,1221 @@
+/*
+ * zsmalloc memory allocator
+ *
+ * Copyright (C) 2011  Nitin Gupta
+ * Copyright (C) 2012, 2013 Minchan Kim
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the license that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ */
+
+
+/*
+ * This allocator is designed for use with zcache and zram. Thus, the
+ * allocator is supposed to work well under low memory conditions. In
+ * particular, it never attempts higher order page allocation which is
+ * very likely to fail under memory pressure. On the other hand, if we
+ * just use single (0-order) pages, it would suffer from very high
+ * fragmentation -- any object of size PAGE_SIZE/2 or larger would occupy
+ * an entire page. This was one of the major issues with its predecessor
+ * (xvmalloc).
+ *
+ * To overcome these issues, zsmalloc allocates a bunch of 0-order pages
+ * and links them together using various 'struct page' fields. These linked
+ * pages act as a single higher-order page i.e. an object can span 0-order
+ * page boundaries. The code refers to these linked pages as a single entity
+ * called zspage.
+ *
+ * Following is how we use various fields and flags of underlying
+ * struct page(s) to form a zspage.
+ *
+ * Usage of struct page fields:
+ *     page->first_page: points to the first component (0-order) page
+ *     page->index (union with page->freelist): offset of the first object
+ *             starting in this page. For the first page, this is
+ *             always 0, so we use this field (aka freelist) to point
+ *             to the first free object in zspage.
+ *     page->lru: links together all component pages (except the first page)
+ *             of a zspage
+ *
+ *     For _first_ page only:
+ *
+ *     page->private (union with page->first_page): refers to the
+ *             component page after the first page
+ *     page->freelist: points to the first free object in zspage.
+ *             Free objects are linked together using in-place
+ *             metadata.
+ *     page->objects: maximum number of objects we can store in this
+ *             zspage (class->zspage_order * PAGE_SIZE / class->size)
+ *     page->lru: links together first pages of various zspages.
+ *             Basically forming list of zspages in a fullness group.
+ *     page->mapping: class index and fullness group of the zspage
+ *
+ * Usage of struct page flags:
+ *     PG_private: identifies the first component page
+ *     PG_private2: identifies the last component page
+ *
+ */
+
+#ifdef CONFIG_ZSMALLOC_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <linux/cpumask.h>
+#include <linux/cpu.h>
+#include <linux/vmalloc.h>
+#include <linux/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/zsmalloc.h>
+#include <linux/zpool.h>
+
+/*
+ * This must be power of 2 and greater than of equal to sizeof(link_free).
+ * These two conditions ensure that any 'struct link_free' itself doesn't
+ * span more than 1 page which avoids complex case of mapping 2 pages simply
+ * to restore link_free pointer values.
+ */
+#define ZS_ALIGN               8
+
+/*
+ * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single)
+ * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N.
+ */
+#define ZS_MAX_ZSPAGE_ORDER 2
+#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
+
+/*
+ * Object location (<PFN>, <obj_idx>) is encoded as
+ * as single (void *) handle value.
+ *
+ * Note that object index <obj_idx> is relative to system
+ * page <PFN> it is stored in, so for each sub-page belonging
+ * to a zspage, obj_idx starts with 0.
+ *
+ * This is made more complicated by various memory models and PAE.
+ */
+
+#ifndef MAX_PHYSMEM_BITS
+#ifdef CONFIG_HIGHMEM64G
+#define MAX_PHYSMEM_BITS 36
+#else /* !CONFIG_HIGHMEM64G */
+/*
+ * If this definition of MAX_PHYSMEM_BITS is used, OBJ_INDEX_BITS will just
+ * be PAGE_SHIFT
+ */
+#define MAX_PHYSMEM_BITS BITS_PER_LONG
+#endif
+#endif
+#define _PFN_BITS              (MAX_PHYSMEM_BITS - PAGE_SHIFT)
+#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS)
+#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1)
+
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
+#define ZS_MIN_ALLOC_SIZE \
+       MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
+#define ZS_MAX_ALLOC_SIZE      PAGE_SIZE
+
+/*
+ * On systems with 4K page size, this gives 255 size classes! There is a
+ * trader-off here:
+ *  - Large number of size classes is potentially wasteful as free page are
+ *    spread across these classes
+ *  - Small number of size classes causes large internal fragmentation
+ *  - Probably its better to use specific size classes (empirically
+ *    determined). NOTE: all those class sizes must be set as multiple of
+ *    ZS_ALIGN to make sure link_free itself never has to span 2 pages.
+ *
+ *  ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN
+ *  (reason above)
+ */
+#define ZS_SIZE_CLASS_DELTA    (PAGE_SIZE >> 8)
+#define ZS_SIZE_CLASSES                ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \
+                                       ZS_SIZE_CLASS_DELTA + 1)
+
+/*
+ * We do not maintain any list for completely empty or full pages
+ */
+enum fullness_group {
+       ZS_ALMOST_FULL,
+       ZS_ALMOST_EMPTY,
+       _ZS_NR_FULLNESS_GROUPS,
+
+       ZS_EMPTY,
+       ZS_FULL
+};
+
+/*
+ * We assign a page to ZS_ALMOST_EMPTY fullness group when:
+ *     n <= N / f, where
+ * n = number of allocated objects
+ * N = total number of objects zspage can store
+ * f = fullness_threshold_frac
+ *
+ * Similarly, we assign zspage to:
+ *     ZS_ALMOST_FULL  when n > N / f
+ *     ZS_EMPTY        when n == 0
+ *     ZS_FULL         when n == N
+ *
+ * (see: fix_fullness_group())
+ */
+static const int fullness_threshold_frac = 4;
+
+struct size_class {
+       /*
+        * Size of objects stored in this class. Must be multiple
+        * of ZS_ALIGN.
+        */
+       int size;
+       unsigned int index;
+
+       /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */
+       int pages_per_zspage;
+
+       spinlock_t lock;
+
+       struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS];
+};
+
+/*
+ * Placed within free objects to form a singly linked list.
+ * For every zspage, first_page->freelist gives head of this list.
+ *
+ * This must be power of 2 and less than or equal to ZS_ALIGN
+ */
+struct link_free {
+       /* Handle of next free chunk (encodes <PFN, obj_idx>) */
+       void *next;
+};
+
+struct zs_pool {
+       struct size_class *size_class[ZS_SIZE_CLASSES];
+
+       gfp_t flags;    /* allocation flags used when growing pool */
+       atomic_long_t pages_allocated;
+};
+
+/*
+ * A zspage's class index and fullness group
+ * are encoded in its (first)page->mapping
+ */
+#define CLASS_IDX_BITS 28
+#define FULLNESS_BITS  4
+#define CLASS_IDX_MASK ((1 << CLASS_IDX_BITS) - 1)
+#define FULLNESS_MASK  ((1 << FULLNESS_BITS) - 1)
+
+/*
+ * By default, zsmalloc uses a copy-based object mapping method to access
+ * allocations that span two pages. However, if a particular architecture
+ * performs VM mapping faster than copying, then it should be added here
+ * so that USE_PGTABLE_MAPPING is defined. This causes zsmalloc to use
+ * page table mapping rather than copying for object mapping.
+*/
+#if defined(CONFIG_ARM) && !defined(MODULE)
+#define USE_PGTABLE_MAPPING
+#endif
+
+struct mapping_area {
+#ifdef USE_PGTABLE_MAPPING
+       struct vm_struct *vm; /* vm area for mapping object that span pages */
+#else
+       char *vm_buf; /* copy buffer for objects that span pages */
+#endif
+       char *vm_addr; /* address of kmap_atomic()'ed pages */
+       enum zs_mapmode vm_mm; /* mapping mode */
+};
+
+/* zpool driver */
+
+#ifdef CONFIG_ZPOOL
+
+static void *zs_zpool_create(gfp_t gfp, struct zpool_ops *zpool_ops)
+{
+       return zs_create_pool(gfp);
+}
+
+static void zs_zpool_destroy(void *pool)
+{
+       zs_destroy_pool(pool);
+}
+
+static int zs_zpool_malloc(void *pool, size_t size, gfp_t gfp,
+                       unsigned long *handle)
+{
+       *handle = zs_malloc(pool, size);
+       return *handle ? 0 : -1;
+}
+static void zs_zpool_free(void *pool, unsigned long handle)
+{
+       zs_free(pool, handle);
+}
+
+static int zs_zpool_shrink(void *pool, unsigned int pages,
+                       unsigned int *reclaimed)
+{
+       return -EINVAL;
+}
+
+static void *zs_zpool_map(void *pool, unsigned long handle,
+                       enum zpool_mapmode mm)
+{
+       enum zs_mapmode zs_mm;
+
+       switch (mm) {
+       case ZPOOL_MM_RO:
+               zs_mm = ZS_MM_RO;
+               break;
+       case ZPOOL_MM_WO:
+               zs_mm = ZS_MM_WO;
+               break;
+       case ZPOOL_MM_RW: /* fallthru */
+       default:
+               zs_mm = ZS_MM_RW;
+               break;
+       }
+
+       return zs_map_object(pool, handle, zs_mm);
+}
+static void zs_zpool_unmap(void *pool, unsigned long handle)
+{
+       zs_unmap_object(pool, handle);
+}
+
+static u64 zs_zpool_total_size(void *pool)
+{
+       return zs_get_total_pages(pool) << PAGE_SHIFT;
+}
+
+static struct zpool_driver zs_zpool_driver = {
+       .type =         "zsmalloc",
+       .owner =        THIS_MODULE,
+       .create =       zs_zpool_create,
+       .destroy =      zs_zpool_destroy,
+       .malloc =       zs_zpool_malloc,
+       .free =         zs_zpool_free,
+       .shrink =       zs_zpool_shrink,
+       .map =          zs_zpool_map,
+       .unmap =        zs_zpool_unmap,
+       .total_size =   zs_zpool_total_size,
+};
+
+MODULE_ALIAS("zpool-zsmalloc");
+#endif /* CONFIG_ZPOOL */
+
+/* per-cpu VM mapping areas for zspage accesses that cross page boundaries */
+static DEFINE_PER_CPU(struct mapping_area, zs_map_area);
+
+static int is_first_page(struct page *page)
+{
+       return PagePrivate(page);
+}
+
+static int is_last_page(struct page *page)
+{
+       return PagePrivate2(page);
+}
+
+static void get_zspage_mapping(struct page *page, unsigned int *class_idx,
+                               enum fullness_group *fullness)
+{
+       unsigned long m;
+       BUG_ON(!is_first_page(page));
+
+       m = (unsigned long)page->mapping;
+       *fullness = m & FULLNESS_MASK;
+       *class_idx = (m >> FULLNESS_BITS) & CLASS_IDX_MASK;
+}
+
+static void set_zspage_mapping(struct page *page, unsigned int class_idx,
+                               enum fullness_group fullness)
+{
+       unsigned long m;
+       BUG_ON(!is_first_page(page));
+
+       m = ((class_idx & CLASS_IDX_MASK) << FULLNESS_BITS) |
+                       (fullness & FULLNESS_MASK);
+       page->mapping = (struct address_space *)m;
+}
+
+static int get_size_class_index(int size)
+{
+       int idx = 0;
+
+       if (likely(size > ZS_MIN_ALLOC_SIZE))
+               idx = DIV_ROUND_UP(size - ZS_MIN_ALLOC_SIZE,
+                               ZS_SIZE_CLASS_DELTA);
+
+       return idx;
+}
+
+static enum fullness_group get_fullness_group(struct page *page)
+{
+       int inuse, max_objects;
+       enum fullness_group fg;
+       BUG_ON(!is_first_page(page));
+
+       inuse = page->inuse;
+       max_objects = page->objects;
+
+       if (inuse == 0)
+               fg = ZS_EMPTY;
+       else if (inuse == max_objects)
+               fg = ZS_FULL;
+       else if (inuse <= max_objects / fullness_threshold_frac)
+               fg = ZS_ALMOST_EMPTY;
+       else
+               fg = ZS_ALMOST_FULL;
+
+       return fg;
+}
+
+static void insert_zspage(struct page *page, struct size_class *class,
+                               enum fullness_group fullness)
+{
+       struct page **head;
+
+       BUG_ON(!is_first_page(page));
+
+       if (fullness >= _ZS_NR_FULLNESS_GROUPS)
+               return;
+
+       head = &class->fullness_list[fullness];
+       if (*head)
+               list_add_tail(&page->lru, &(*head)->lru);
+
+       *head = page;
+}
+
+static void remove_zspage(struct page *page, struct size_class *class,
+                               enum fullness_group fullness)
+{
+       struct page **head;
+
+       BUG_ON(!is_first_page(page));
+
+       if (fullness >= _ZS_NR_FULLNESS_GROUPS)
+               return;
+
+       head = &class->fullness_list[fullness];
+       BUG_ON(!*head);
+       if (list_empty(&(*head)->lru))
+               *head = NULL;
+       else if (*head == page)
+               *head = (struct page *)list_entry((*head)->lru.next,
+                                       struct page, lru);
+
+       list_del_init(&page->lru);
+}
+
+static enum fullness_group fix_fullness_group(struct zs_pool *pool,
+                                               struct page *page)
+{
+       int class_idx;
+       struct size_class *class;
+       enum fullness_group currfg, newfg;
+
+       BUG_ON(!is_first_page(page));
+
+       get_zspage_mapping(page, &class_idx, &currfg);
+       newfg = get_fullness_group(page);
+       if (newfg == currfg)
+               goto out;
+
+       class = pool->size_class[class_idx];
+       remove_zspage(page, class, currfg);
+       insert_zspage(page, class, newfg);
+       set_zspage_mapping(page, class_idx, newfg);
+
+out:
+       return newfg;
+}
+
+/*
+ * We have to decide on how many pages to link together
+ * to form a zspage for each size class. This is important
+ * to reduce wastage due to unusable space left at end of
+ * each zspage which is given as:
+ *     wastage = Zp - Zp % size_class
+ * where Zp = zspage size = k * PAGE_SIZE where k = 1, 2, ...
+ *
+ * For example, for size class of 3/8 * PAGE_SIZE, we should
+ * link together 3 PAGE_SIZE sized pages to form a zspage
+ * since then we can perfectly fit in 8 such objects.
+ */
+static int get_pages_per_zspage(int class_size)
+{
+       int i, max_usedpc = 0;
+       /* zspage order which gives maximum used size per KB */
+       int max_usedpc_order = 1;
+
+       for (i = 1; i <= ZS_MAX_PAGES_PER_ZSPAGE; i++) {
+               int zspage_size;
+               int waste, usedpc;
+
+               zspage_size = i * PAGE_SIZE;
+               waste = zspage_size % class_size;
+               usedpc = (zspage_size - waste) * 100 / zspage_size;
+
+               if (usedpc > max_usedpc) {
+                       max_usedpc = usedpc;
+                       max_usedpc_order = i;
+               }
+       }
+
+       return max_usedpc_order;
+}
+
+/*
+ * A single 'zspage' is composed of many system pages which are
+ * linked together using fields in struct page. This function finds
+ * the first/head page, given any component page of a zspage.
+ */
+static struct page *get_first_page(struct page *page)
+{
+       if (is_first_page(page))
+               return page;
+       else
+               return page->first_page;
+}
+
+static struct page *get_next_page(struct page *page)
+{
+       struct page *next;
+
+       if (is_last_page(page))
+               next = NULL;
+       else if (is_first_page(page))
+               next = (struct page *)page->private;
+       else
+               next = list_entry(page->lru.next, struct page, lru);
+
+       return next;
+}
+
+/*
+ * Encode <page, obj_idx> as a single handle value.
+ * On hardware platforms with physical memory starting at 0x0 the pfn
+ * could be 0 so we ensure that the handle will never be 0 by adjusting the
+ * encoded obj_idx value before encoding.
+ */
+static void *obj_location_to_handle(struct page *page, unsigned long obj_idx)
+{
+       unsigned long handle;
+
+       if (!page) {
+               BUG_ON(obj_idx);
+               return NULL;
+       }
+
+       handle = page_to_pfn(page) << OBJ_INDEX_BITS;
+       handle |= ((obj_idx + 1) & OBJ_INDEX_MASK);
+
+       return (void *)handle;
+}
+
+/*
+ * Decode <page, obj_idx> pair from the given object handle. We adjust the
+ * decoded obj_idx back to its original value since it was adjusted in
+ * obj_location_to_handle().
+ */
+static void obj_handle_to_location(unsigned long handle, struct page **page,
+                               unsigned long *obj_idx)
+{
+       *page = pfn_to_page(handle >> OBJ_INDEX_BITS);
+       *obj_idx = (handle & OBJ_INDEX_MASK) - 1;
+}
+
+static unsigned long obj_idx_to_offset(struct page *page,
+                               unsigned long obj_idx, int class_size)
+{
+       unsigned long off = 0;
+
+       if (!is_first_page(page))
+               off = page->index;
+
+       return off + obj_idx * class_size;
+}
+
+static void reset_page(struct page *page)
+{
+       clear_bit(PG_private, &page->flags);
+       clear_bit(PG_private_2, &page->flags);
+       set_page_private(page, 0);
+       page->mapping = NULL;
+       page->freelist = NULL;
+       page_mapcount_reset(page);
+}
+
+static void free_zspage(struct page *first_page)
+{
+       struct page *nextp, *tmp, *head_extra;
+
+       BUG_ON(!is_first_page(first_page));
+       BUG_ON(first_page->inuse);
+
+       head_extra = (struct page *)page_private(first_page);
+
+       reset_page(first_page);
+       __free_page(first_page);
+
+       /* zspage with only 1 system page */
+       if (!head_extra)
+               return;
+
+       list_for_each_entry_safe(nextp, tmp, &head_extra->lru, lru) {
+               list_del(&nextp->lru);
+               reset_page(nextp);
+               __free_page(nextp);
+       }
+       reset_page(head_extra);
+       __free_page(head_extra);
+}
+
+/* Initialize a newly allocated zspage */
+static void init_zspage(struct page *first_page, struct size_class *class)
+{
+       unsigned long off = 0;
+       struct page *page = first_page;
+
+       BUG_ON(!is_first_page(first_page));
+       while (page) {
+               struct page *next_page;
+               struct link_free *link;
+               unsigned int i = 1;
+               void *vaddr;
+
+               /*
+                * page->index stores offset of first object starting
+                * in the page. For the first page, this is always 0,
+                * so we use first_page->index (aka ->freelist) to store
+                * head of corresponding zspage's freelist.
+                */
+               if (page != first_page)
+                       page->index = off;
+
+               vaddr = kmap_atomic(page);
+               link = (struct link_free *)vaddr + off / sizeof(*link);
+
+               while ((off += class->size) < PAGE_SIZE) {
+                       link->next = obj_location_to_handle(page, i++);
+                       link += class->size / sizeof(*link);
+               }
+
+               /*
+                * We now come to the last (full or partial) object on this
+                * page, which must point to the first object on the next
+                * page (if present)
+                */
+               next_page = get_next_page(page);
+               link->next = obj_location_to_handle(next_page, 0);
+               kunmap_atomic(vaddr);
+               page = next_page;
+               off %= PAGE_SIZE;
+       }
+}
+
+/*
+ * Allocate a zspage for the given size class
+ */
+static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
+{
+       int i, error;
+       struct page *first_page = NULL, *uninitialized_var(prev_page);
+
+       /*
+        * Allocate individual pages and link them together as:
+        * 1. first page->private = first sub-page
+        * 2. all sub-pages are linked together using page->lru
+        * 3. each sub-page is linked to the first page using page->first_page
+        *
+        * For each size class, First/Head pages are linked together using
+        * page->lru. Also, we set PG_private to identify the first page
+        * (i.e. no other sub-page has this flag set) and PG_private_2 to
+        * identify the last page.
+        */
+       error = -ENOMEM;
+       for (i = 0; i < class->pages_per_zspage; i++) {
+               struct page *page;
+
+               page = alloc_page(flags);
+               if (!page)
+                       goto cleanup;
+
+               INIT_LIST_HEAD(&page->lru);
+               if (i == 0) {   /* first page */
+                       SetPagePrivate(page);
+                       set_page_private(page, 0);
+                       first_page = page;
+                       first_page->inuse = 0;
+               }
+               if (i == 1)
+                       first_page->private = (unsigned long)page;
+               if (i >= 1)
+                       page->first_page = first_page;
+               if (i >= 2)
+                       list_add(&page->lru, &prev_page->lru);
+               if (i == class->pages_per_zspage - 1)   /* last page */
+                       SetPagePrivate2(page);
+               prev_page = page;
+       }
+
+       init_zspage(first_page, class);
+
+       first_page->freelist = obj_location_to_handle(first_page, 0);
+       /* Maximum number of objects we can store in this zspage */
+       first_page->objects = class->pages_per_zspage * PAGE_SIZE / class->size;
+
+       error = 0; /* Success */
+
+cleanup:
+       if (unlikely(error) && first_page) {
+               free_zspage(first_page);
+               first_page = NULL;
+       }
+
+       return first_page;
+}
+
+static struct page *find_get_zspage(struct size_class *class)
+{
+       int i;
+       struct page *page;
+
+       for (i = 0; i < _ZS_NR_FULLNESS_GROUPS; i++) {
+               page = class->fullness_list[i];
+               if (page)
+                       break;
+       }
+
+       return page;
+}
+
+#ifdef USE_PGTABLE_MAPPING
+static inline int __zs_cpu_up(struct mapping_area *area)
+{
+       /*
+        * Make sure we don't leak memory if a cpu UP notification
+        * and zs_init() race and both call zs_cpu_up() on the same cpu
+        */
+       if (area->vm)
+               return 0;
+       area->vm = alloc_vm_area(PAGE_SIZE * 2, NULL);
+       if (!area->vm)
+               return -ENOMEM;
+       return 0;
+}
+
+static inline void __zs_cpu_down(struct mapping_area *area)
+{
+       if (area->vm)
+               free_vm_area(area->vm);
+       area->vm = NULL;
+}
+
+static inline void *__zs_map_object(struct mapping_area *area,
+                               struct page *pages[2], int off, int size)
+{
+       BUG_ON(map_vm_area(area->vm, PAGE_KERNEL, &pages));
+       area->vm_addr = area->vm->addr;
+       return area->vm_addr + off;
+}
+
+static inline void __zs_unmap_object(struct mapping_area *area,
+                               struct page *pages[2], int off, int size)
+{
+       unsigned long addr = (unsigned long)area->vm_addr;
+
+       unmap_kernel_range(addr, PAGE_SIZE * 2);
+}
+
+#else /* USE_PGTABLE_MAPPING */
+
+static inline int __zs_cpu_up(struct mapping_area *area)
+{
+       /*
+        * Make sure we don't leak memory if a cpu UP notification
+        * and zs_init() race and both call zs_cpu_up() on the same cpu
+        */
+       if (area->vm_buf)
+               return 0;
+       area->vm_buf = (char *)__get_free_page(GFP_KERNEL);
+       if (!area->vm_buf)
+               return -ENOMEM;
+       return 0;
+}
+
+static inline void __zs_cpu_down(struct mapping_area *area)
+{
+       if (area->vm_buf)
+               free_page((unsigned long)area->vm_buf);
+       area->vm_buf = NULL;
+}
+
+static void *__zs_map_object(struct mapping_area *area,
+                       struct page *pages[2], int off, int size)
+{
+       int sizes[2];
+       void *addr;
+       char *buf = area->vm_buf;
+
+       /* disable page faults to match kmap_atomic() return conditions */
+       pagefault_disable();
+
+       /* no read fastpath */
+       if (area->vm_mm == ZS_MM_WO)
+               goto out;
+
+       sizes[0] = PAGE_SIZE - off;
+       sizes[1] = size - sizes[0];
+
+       /* copy object to per-cpu buffer */
+       addr = kmap_atomic(pages[0]);
+       memcpy(buf, addr + off, sizes[0]);
+       kunmap_atomic(addr);
+       addr = kmap_atomic(pages[1]);
+       memcpy(buf + sizes[0], addr, sizes[1]);
+       kunmap_atomic(addr);
+out:
+       return area->vm_buf;
+}
+
+static void __zs_unmap_object(struct mapping_area *area,
+                       struct page *pages[2], int off, int size)
+{
+       int sizes[2];
+       void *addr;
+       char *buf = area->vm_buf;
+
+       /* no write fastpath */
+       if (area->vm_mm == ZS_MM_RO)
+               goto out;
+
+       sizes[0] = PAGE_SIZE - off;
+       sizes[1] = size - sizes[0];
+
+       /* copy per-cpu buffer to object */
+       addr = kmap_atomic(pages[0]);
+       memcpy(addr + off, buf, sizes[0]);
+       kunmap_atomic(addr);
+       addr = kmap_atomic(pages[1]);
+       memcpy(addr, buf + sizes[0], sizes[1]);
+       kunmap_atomic(addr);
+
+out:
+       /* enable page faults to match kunmap_atomic() return conditions */
+       pagefault_enable();
+}
+
+#endif /* USE_PGTABLE_MAPPING */
+
+static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action,
+                               void *pcpu)
+{
+       int ret, cpu = (long)pcpu;
+       struct mapping_area *area;
+
+       switch (action) {
+       case CPU_UP_PREPARE:
+               area = &per_cpu(zs_map_area, cpu);
+               ret = __zs_cpu_up(area);
+               if (ret)
+                       return notifier_from_errno(ret);
+               break;
+       case CPU_DEAD:
+       case CPU_UP_CANCELED:
+               area = &per_cpu(zs_map_area, cpu);
+               __zs_cpu_down(area);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block zs_cpu_nb = {
+       .notifier_call = zs_cpu_notifier
+};
+
+static void zs_unregister_cpu_notifier(void)
+{
+       int cpu;
+
+       cpu_notifier_register_begin();
+
+       for_each_online_cpu(cpu)
+               zs_cpu_notifier(NULL, CPU_DEAD, (void *)(long)cpu);
+       __unregister_cpu_notifier(&zs_cpu_nb);
+
+       cpu_notifier_register_done();
+}
+
+static int zs_register_cpu_notifier(void)
+{
+       int cpu, uninitialized_var(ret);
+
+       cpu_notifier_register_begin();
+
+       __register_cpu_notifier(&zs_cpu_nb);
+       for_each_online_cpu(cpu) {
+               ret = zs_cpu_notifier(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
+               if (notifier_to_errno(ret))
+                       break;
+       }
+
+       cpu_notifier_register_done();
+       return notifier_to_errno(ret);
+}
+
+static void __exit zs_exit(void)
+{
+#ifdef CONFIG_ZPOOL
+       zpool_unregister_driver(&zs_zpool_driver);
+#endif
+       zs_unregister_cpu_notifier();
+}
+
+static int __init zs_init(void)
+{
+       int ret = zs_register_cpu_notifier();
+
+       if (ret) {
+               zs_unregister_cpu_notifier();
+               return ret;
+       }
+
+#ifdef CONFIG_ZPOOL
+       zpool_register_driver(&zs_zpool_driver);
+#endif
+       return 0;
+}
+
+static unsigned int get_maxobj_per_zspage(int size, int pages_per_zspage)
+{
+       return pages_per_zspage * PAGE_SIZE / size;
+}
+
+static bool can_merge(struct size_class *prev, int size, int pages_per_zspage)
+{
+       if (prev->pages_per_zspage != pages_per_zspage)
+               return false;
+
+       if (get_maxobj_per_zspage(prev->size, prev->pages_per_zspage)
+               != get_maxobj_per_zspage(size, pages_per_zspage))
+               return false;
+
+       return true;
+}
+
+/**
+ * zs_create_pool - Creates an allocation pool to work from.
+ * @flags: allocation flags used to allocate pool metadata
+ *
+ * This function must be called before anything when using
+ * the zsmalloc allocator.
+ *
+ * On success, a pointer to the newly created pool is returned,
+ * otherwise NULL.
+ */
+struct zs_pool *zs_create_pool(gfp_t flags)
+{
+       int i, ovhd_size;
+       struct zs_pool *pool;
+
+       ovhd_size = roundup(sizeof(*pool), PAGE_SIZE);
+       pool = kzalloc(ovhd_size, GFP_KERNEL);
+       if (!pool)
+               return NULL;
+
+       /*
+        * Iterate reversly, because, size of size_class that we want to use
+        * for merging should be larger or equal to current size.
+        */
+       for (i = ZS_SIZE_CLASSES - 1; i >= 0; i--) {
+               int size;
+               int pages_per_zspage;
+               struct size_class *class;
+               struct size_class *prev_class;
+
+               size = ZS_MIN_ALLOC_SIZE + i * ZS_SIZE_CLASS_DELTA;
+               if (size > ZS_MAX_ALLOC_SIZE)
+                       size = ZS_MAX_ALLOC_SIZE;
+               pages_per_zspage = get_pages_per_zspage(size);
+
+               /*
+                * size_class is used for normal zsmalloc operation such
+                * as alloc/free for that size. Although it is natural that we
+                * have one size_class for each size, there is a chance that we
+                * can get more memory utilization if we use one size_class for
+                * many different sizes whose size_class have same
+                * characteristics. So, we makes size_class point to
+                * previous size_class if possible.
+                */
+               if (i < ZS_SIZE_CLASSES - 1) {
+                       prev_class = pool->size_class[i + 1];
+                       if (can_merge(prev_class, size, pages_per_zspage)) {
+                               pool->size_class[i] = prev_class;
+                               continue;
+                       }
+               }
+
+               class = kzalloc(sizeof(struct size_class), GFP_KERNEL);
+               if (!class)
+                       goto err;
+
+               class->size = size;
+               class->index = i;
+               class->pages_per_zspage = pages_per_zspage;
+               spin_lock_init(&class->lock);
+               pool->size_class[i] = class;
+       }
+
+       pool->flags = flags;
+
+       return pool;
+
+err:
+       zs_destroy_pool(pool);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(zs_create_pool);
+
+void zs_destroy_pool(struct zs_pool *pool)
+{
+       int i;
+
+       for (i = 0; i < ZS_SIZE_CLASSES; i++) {
+               int fg;
+               struct size_class *class = pool->size_class[i];
+
+               if (!class)
+                       continue;
+
+               if (class->index != i)
+                       continue;
+
+               for (fg = 0; fg < _ZS_NR_FULLNESS_GROUPS; fg++) {
+                       if (class->fullness_list[fg]) {
+                               pr_info("Freeing non-empty class with size "
+                                       "%db, fullness group %d\n",
+                                       class->size, fg);
+                       }
+               }
+               kfree(class);
+       }
+       kfree(pool);
+}
+EXPORT_SYMBOL_GPL(zs_destroy_pool);
+
+/**
+ * zs_malloc - Allocate block of given size from pool.
+ * @pool: pool to allocate from
+ * @size: size of block to allocate
+ *
+ * On success, handle to the allocated object is returned,
+ * otherwise 0.
+ * Allocation requests with size > ZS_MAX_ALLOC_SIZE will fail.
+ */
+unsigned long zs_malloc(struct zs_pool *pool, size_t size)
+{
+       unsigned long obj;
+       struct link_free *link;
+       struct size_class *class;
+       void *vaddr;
+
+       struct page *first_page, *m_page;
+       unsigned long m_objidx, m_offset;
+
+       if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE))
+               return 0;
+
+       class = pool->size_class[get_size_class_index(size)];
+
+       spin_lock(&class->lock);
+       first_page = find_get_zspage(class);
+
+       if (!first_page) {
+               spin_unlock(&class->lock);
+               first_page = alloc_zspage(class, pool->flags);
+               if (unlikely(!first_page))
+                       return 0;
+
+               set_zspage_mapping(first_page, class->index, ZS_EMPTY);
+               atomic_long_add(class->pages_per_zspage,
+                                       &pool->pages_allocated);
+               spin_lock(&class->lock);
+       }
+
+       obj = (unsigned long)first_page->freelist;
+       obj_handle_to_location(obj, &m_page, &m_objidx);
+       m_offset = obj_idx_to_offset(m_page, m_objidx, class->size);
+
+       vaddr = kmap_atomic(m_page);
+       link = (struct link_free *)vaddr + m_offset / sizeof(*link);
+       first_page->freelist = link->next;
+       memset(link, POISON_INUSE, sizeof(*link));
+       kunmap_atomic(vaddr);
+
+       first_page->inuse++;
+       /* Now move the zspage to another fullness group, if required */
+       fix_fullness_group(pool, first_page);
+       spin_unlock(&class->lock);
+
+       return obj;
+}
+EXPORT_SYMBOL_GPL(zs_malloc);
+
+void zs_free(struct zs_pool *pool, unsigned long obj)
+{
+       struct link_free *link;
+       struct page *first_page, *f_page;
+       unsigned long f_objidx, f_offset;
+       void *vaddr;
+
+       int class_idx;
+       struct size_class *class;
+       enum fullness_group fullness;
+
+       if (unlikely(!obj))
+               return;
+
+       obj_handle_to_location(obj, &f_page, &f_objidx);
+       first_page = get_first_page(f_page);
+
+       get_zspage_mapping(first_page, &class_idx, &fullness);
+       class = pool->size_class[class_idx];
+       f_offset = obj_idx_to_offset(f_page, f_objidx, class->size);
+
+       spin_lock(&class->lock);
+
+       /* Insert this object in containing zspage's freelist */
+       vaddr = kmap_atomic(f_page);
+       link = (struct link_free *)(vaddr + f_offset);
+       link->next = first_page->freelist;
+       kunmap_atomic(vaddr);
+       first_page->freelist = (void *)obj;
+
+       first_page->inuse--;
+       fullness = fix_fullness_group(pool, first_page);
+       spin_unlock(&class->lock);
+
+       if (fullness == ZS_EMPTY) {
+               atomic_long_sub(class->pages_per_zspage,
+                               &pool->pages_allocated);
+               free_zspage(first_page);
+       }
+}
+EXPORT_SYMBOL_GPL(zs_free);
+
+/**
+ * zs_map_object - get address of allocated object from handle.
+ * @pool: pool from which the object was allocated
+ * @handle: handle returned from zs_malloc
+ *
+ * Before using an object allocated from zs_malloc, it must be mapped using
+ * this function. When done with the object, it must be unmapped using
+ * zs_unmap_object.
+ *
+ * Only one object can be mapped per cpu at a time. There is no protection
+ * against nested mappings.
+ *
+ * This function returns with preemption and page faults disabled.
+*/
+void *zs_map_object(struct zs_pool *pool, unsigned long handle,
+                       enum zs_mapmode mm)
+{
+       struct page *page;
+       unsigned long obj_idx, off;
+
+       unsigned int class_idx;
+       enum fullness_group fg;
+       struct size_class *class;
+       struct mapping_area *area;
+       struct page *pages[2];
+
+       BUG_ON(!handle);
+
+       /*
+        * Because we use per-cpu mapping areas shared among the
+        * pools/users, we can't allow mapping in interrupt context
+        * because it can corrupt another users mappings.
+        */
+       BUG_ON(in_interrupt());
+
+       obj_handle_to_location(handle, &page, &obj_idx);
+       get_zspage_mapping(get_first_page(page), &class_idx, &fg);
+       class = pool->size_class[class_idx];
+       off = obj_idx_to_offset(page, obj_idx, class->size);
+
+       area = &get_cpu_var(zs_map_area);
+       area->vm_mm = mm;
+       if (off + class->size <= PAGE_SIZE) {
+               /* this object is contained entirely within a page */
+               area->vm_addr = kmap_atomic(page);
+               return area->vm_addr + off;
+       }
+
+       /* this object spans two pages */
+       pages[0] = page;
+       pages[1] = get_next_page(page);
+       BUG_ON(!pages[1]);
+
+       return __zs_map_object(area, pages, off, class->size);
+}
+EXPORT_SYMBOL_GPL(zs_map_object);
+
+void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
+{
+       struct page *page;
+       unsigned long obj_idx, off;
+
+       unsigned int class_idx;
+       enum fullness_group fg;
+       struct size_class *class;
+       struct mapping_area *area;
+
+       BUG_ON(!handle);
+
+       obj_handle_to_location(handle, &page, &obj_idx);
+       get_zspage_mapping(get_first_page(page), &class_idx, &fg);
+       class = pool->size_class[class_idx];
+       off = obj_idx_to_offset(page, obj_idx, class->size);
+
+       area = &__get_cpu_var(zs_map_area);
+       if (off + class->size <= PAGE_SIZE)
+               kunmap_atomic(area->vm_addr);
+       else {
+               struct page *pages[2];
+
+               pages[0] = page;
+               pages[1] = get_next_page(page);
+               BUG_ON(!pages[1]);
+
+               __zs_unmap_object(area, pages, off, class->size);
+       }
+       put_cpu_var(zs_map_area);
+}
+EXPORT_SYMBOL_GPL(zs_unmap_object);
+
+unsigned long zs_get_total_pages(struct zs_pool *pool)
+{
+       return atomic_long_read(&pool->pages_allocated);
+}
+EXPORT_SYMBOL_GPL(zs_get_total_pages);
+
+module_init(zs_init);
+module_exit(zs_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
index 31ee5c6033dfe6ec87d9adfacb688025faeda2bc..479e8a63125af5b1307be42334c29c6de1ccf891 100644 (file)
@@ -126,6 +126,9 @@ int ip_forward(struct sk_buff *skb)
        struct rtable *rt;      /* Route we use */
        struct ip_options *opt  = &(IPCB(skb)->opt);
 
+       if (unlikely(skb->sk))
+               goto drop;
+
        if (skb_warn_if_lro(skb))
                goto drop;
 
index 58c3a3cea4df18141380d564024b2602ebaf3a81..47d1c7e10d5479ab1fff871cf07382cc4db093dc 100644 (file)
@@ -154,6 +154,7 @@ void ping_unhash(struct sock *sk)
        if (sk_hashed(sk)) {
                write_lock_bh(&ping_table.lock);
                hlist_nulls_del(&sk->sk_nulls_node);
+               sk_nulls_node_init(&sk->sk_nulls_node);
                sock_put(sk);
                isk->inet_num = 0;
                isk->inet_sport = 0;
index 834857f3c8713e8d8b80ab7b4f413725ec0ca9b4..86183c4e4fd54a231933e09bd3d0b62c8228699e 100644 (file)
@@ -23,7 +23,6 @@
 #define ALPHA_MIN      ((3*ALPHA_SCALE)/10)    /* ~0.3 */
 #define ALPHA_MAX      (10*ALPHA_SCALE)        /* 10.0 */
 #define ALPHA_BASE     ALPHA_SCALE             /* 1.0 */
-#define U32_MAX                ((u32)~0U)
 #define RTT_MAX                (U32_MAX / ALPHA_MAX)   /* 3.3 secs */
 
 #define BETA_SHIFT     6
index 7aa7faa7c3dde7911c3b10ed4760aa93d7e7a4a4..22fc869465e8b17b43208b6424f553531b593f21 100644 (file)
@@ -3077,10 +3077,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                        if (seq_rtt < 0) {
                                seq_rtt = ca_seq_rtt;
                        }
-                       if (!(sacked & TCPCB_SACKED_ACKED))
+                       if (!(sacked & TCPCB_SACKED_ACKED)) {
                                reord = min(pkts_acked, reord);
-                       if (!after(scb->end_seq, tp->high_seq))
-                               flag |= FLAG_ORIG_SACK_ACKED;
+                               if (!after(scb->end_seq, tp->high_seq))
+                                       flag |= FLAG_ORIG_SACK_ACKED;
+                       }
                }
 
                if (sacked & TCPCB_SACKED_ACKED)
index 8e374e566932e70a52cabe7d12a63fc6734a31ee..d64453a81028cc2b0eb787c349a50ebe75bad425 100644 (file)
@@ -1902,7 +1902,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
                skb->sk = sk;
                skb->destructor = sock_edemux;
                if (sk->sk_state != TCP_TIME_WAIT) {
-                       struct dst_entry *dst = sk->sk_rx_dst;
+                       struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst);
 
                        if (dst)
                                dst = dst_check(dst, 0);
index f755a8326e88273c78df073117d556afac780c4e..5653febcb2ac51bdb1c20cf1ba24e39968153b65 100644 (file)
@@ -2570,39 +2570,65 @@ begin_fwd:
        }
 }
 
-/* Send a fin.  The caller locks the socket for us.  This cannot be
- * allowed to fail queueing a FIN frame under any circumstances.
+/* We allow to exceed memory limits for FIN packets to expedite
+ * connection tear down and (memory) recovery.
+ * Otherwise tcp_send_fin() could be tempted to either delay FIN
+ * or even be forced to close flow without any FIN.
+ */
+static void sk_forced_wmem_schedule(struct sock *sk, int size)
+{
+       int amt, status;
+
+       if (size <= sk->sk_forward_alloc)
+               return;
+       amt = sk_mem_pages(size);
+       sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
+       sk_memory_allocated_add(sk, amt, &status);
+}
+
+/* Send a FIN. The caller locks the socket for us.
+ * We should try to send a FIN packet really hard, but eventually give up.
  */
 void tcp_send_fin(struct sock *sk)
 {
+       struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk);
        struct tcp_sock *tp = tcp_sk(sk);
-       struct sk_buff *skb = tcp_write_queue_tail(sk);
-       int mss_now;
 
-       /* Optimization, tack on the FIN if we have a queue of
-        * unsent frames.  But be careful about outgoing SACKS
-        * and IP options.
+       /* Optimization, tack on the FIN if we have one skb in write queue and
+        * this skb was not yet sent, or we are under memory pressure.
+        * Note: in the latter case, FIN packet will be sent after a timeout,
+        * as TCP stack thinks it has already been transmitted.
         */
-       mss_now = tcp_current_mss(sk);
-
-       if (tcp_send_head(sk) != NULL) {
-               TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN;
-               TCP_SKB_CB(skb)->end_seq++;
+       if (tskb && (tcp_send_head(sk) || sk_under_memory_pressure(sk))) {
+coalesce:
+               TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN;
+               TCP_SKB_CB(tskb)->end_seq++;
                tp->write_seq++;
+               if (!tcp_send_head(sk)) {
+                       /* This means tskb was already sent.
+                        * Pretend we included the FIN on previous transmit.
+                        * We need to set tp->snd_nxt to the value it would have
+                        * if FIN had been sent. This is because retransmit path
+                        * does not change tp->snd_nxt.
+                        */
+                       tp->snd_nxt++;
+                       return;
+               }
        } else {
-               /* Socket is locked, keep trying until memory is available. */
-               for (;;) {
-                       skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
-                       if (skb)
-                               break;
-                       yield();
+               skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation);
+               if (unlikely(!skb)) {
+                       if (tskb)
+                               goto coalesce;
+                       return;
                }
+               skb_reserve(skb, MAX_TCP_HEADER);
+               sk_forced_wmem_schedule(sk, skb->truesize);
                /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
                tcp_init_nondata_skb(skb, tp->write_seq,
                                     TCPHDR_ACK | TCPHDR_FIN);
                tcp_queue_skb(sk, skb);
        }
-       __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF);
+       __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF);
 }
 
 /* We get here when a process closes a file descriptor (either due to
@@ -2771,6 +2797,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        }
 #endif
 
+       /* Do not fool tcpdump (if any), clean our debris */
+       skb->tstamp.tv64 = 0;
        return skb;
 }
 EXPORT_SYMBOL(tcp_make_synack);
@@ -2908,6 +2936,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
                goto fallback;
        syn_data->ip_summed = CHECKSUM_PARTIAL;
        memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
+       skb_shinfo(syn_data)->gso_segs = 1;
        if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space),
                                         fo->data->msg_iov, 0, space))) {
                kfree_skb(syn_data);
index 060a0449acaa960433f0fd561329b66bf0f31056..05f361338c2eabd0d27449cd8d85a3c29e19046d 100644 (file)
@@ -1193,7 +1193,14 @@ static void ndisc_router_discovery(struct sk_buff *skb)
        if (rt)
                rt6_set_expires(rt, jiffies + (HZ * lifetime));
        if (ra_msg->icmph.icmp6_hop_limit) {
-               in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
+               /* Only set hop_limit on the interface if it is higher than
+                * the current hop_limit.
+                */
+               if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) {
+                       in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
+               } else {
+                       ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n");
+               }
                if (rt)
                        dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
                                       ra_msg->icmph.icmp6_hop_limit);
index 0acad490d9d77c2152db760e7f5b490d6456e115..a4738211c60107406dab101a1730d70442afbb8b 100644 (file)
@@ -1619,7 +1619,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
                skb->sk = sk;
                skb->destructor = sock_edemux;
                if (sk->sk_state != TCP_TIME_WAIT) {
-                       struct dst_entry *dst = sk->sk_rx_dst;
+                       struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst);
 
                        if (dst)
                                dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
index 612a5ddaf93b1ab1b5a524c5efef8d6b1f769038..799bafc2af39ea191e3753c88c3f921e44a77162 100644 (file)
@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = {
        {
                .procname       = "ack",
                .data           = &sysctl_llc2_ack_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_ack_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
        {
                .procname       = "busy",
                .data           = &sysctl_llc2_busy_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_busy_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
        {
                .procname       = "p",
                .data           = &sysctl_llc2_p_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_p_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
        {
                .procname       = "rej",
                .data           = &sysctl_llc2_rej_timeout,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(sysctl_llc2_rej_timeout),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
index d25f293776482f5e88c831c290058f2ca2e6af2b..957c1db6665254645f43d0c04456015a1d4df65c 100644 (file)
 
 static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
 
+static bool nf_generic_should_process(u8 proto)
+{
+       switch (proto) {
+#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE
+       case IPPROTO_SCTP:
+               return false;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE
+       case IPPROTO_DCCP:
+               return false;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE
+       case IPPROTO_GRE:
+               return false;
+#endif
+#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE
+       case IPPROTO_UDPLITE:
+               return false;
+#endif
+       default:
+               return true;
+       }
+}
+
 static inline struct nf_generic_net *generic_pernet(struct net *net)
 {
        return &net->ct.nf_ct_proto.generic;
@@ -67,7 +91,7 @@ static int generic_packet(struct nf_conn *ct,
 static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
                        unsigned int dataoff, unsigned int *timeouts)
 {
-       return true;
+       return nf_generic_should_process(nf_ct_protonum(ct));
 }
 
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
index f6562ba97a978a8b9deeb433e922d5d6fb28ea8f..ddf77f7fbe245069b9f5d151f974d5b98b220282 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/suspend.h>
 #include <linux/notifier.h>
 #include <net/net_namespace.h>
+#include <net/sock.h>
 
 struct idletimer_tg_attr {
        struct attribute attr;
@@ -73,6 +74,7 @@ struct idletimer_tg {
        bool work_pending;
        bool send_nl_msg;
        bool active;
+       uid_t uid;
 };
 
 static LIST_HEAD(idletimer_tg_list);
@@ -117,7 +119,8 @@ static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer)
        char iface_msg[NLMSG_MAX_SIZE];
        char state_msg[NLMSG_MAX_SIZE];
        char timestamp_msg[NLMSG_MAX_SIZE];
-       char *envp[] = { iface_msg, state_msg, timestamp_msg, NULL };
+       char uid_msg[NLMSG_MAX_SIZE];
+       char *envp[] = { iface_msg, state_msg, timestamp_msg, uid_msg, NULL };
        int res;
        struct timespec ts;
        uint64_t time_ns;
@@ -140,6 +143,16 @@ static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer)
                return;
        }
 
+       if (state) {
+               res = snprintf(uid_msg, NLMSG_MAX_SIZE, "UID=%u", timer->uid);
+               if (NLMSG_MAX_SIZE <= res)
+                       pr_err("message too long (%d)", res);
+       } else {
+               res = snprintf(uid_msg, NLMSG_MAX_SIZE, "UID=");
+               if (NLMSG_MAX_SIZE <= res)
+                       pr_err("message too long (%d)", res);
+       }
+
        time_ns = timespec_to_ns(&ts);
        res = snprintf(timestamp_msg, NLMSG_MAX_SIZE, "TIME_NS=%llu", time_ns);
        if (NLMSG_MAX_SIZE <= res) {
@@ -147,7 +160,8 @@ static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer)
                pr_err("message too long (%d)", res);
        }
 
-       pr_debug("putting nlmsg: <%s> <%s>\n", iface_msg, state_msg);
+       pr_debug("putting nlmsg: <%s> <%s> <%s> <%s>\n", iface_msg, state_msg,
+                timestamp_msg, uid_msg);
        kobject_uevent_env(idletimer_tg_kobj, KOBJ_CHANGE, envp);
        return;
 
@@ -298,6 +312,7 @@ static int idletimer_tg_create(struct idletimer_tg_info *info)
        info->timer->delayed_timer_trigger.tv_sec = 0;
        info->timer->delayed_timer_trigger.tv_nsec = 0;
        info->timer->work_pending = false;
+       info->timer->uid = 0;
        get_monotonic_boottime(&info->timer->last_modified_timer);
 
        info->timer->pm_nb.notifier_call = idletimer_resume;
@@ -321,7 +336,8 @@ out:
        return ret;
 }
 
-static void reset_timer(const struct idletimer_tg_info *info)
+static void reset_timer(const struct idletimer_tg_info *info,
+                       struct sk_buff *skb)
 {
        unsigned long now = jiffies;
        struct idletimer_tg *timer = info->timer;
@@ -334,6 +350,17 @@ static void reset_timer(const struct idletimer_tg_info *info)
        if (!timer_prev || time_before(timer->timer.expires, now)) {
                pr_debug("Starting Checkentry timer (Expired, Jiffies): %lu, %lu\n",
                                timer->timer.expires, now);
+
+               /* Stores the uid resposible for waking up the radio */
+               if (skb && (skb->sk)) {
+                       struct sock *sk = skb->sk;
+                       read_lock_bh(&sk->sk_callback_lock);
+                       if ((sk->sk_socket) && (sk->sk_socket->file) &&
+                   (sk->sk_socket->file->f_cred))
+                               timer->uid = sk->sk_socket->file->f_cred->uid;
+                       read_unlock_bh(&sk->sk_callback_lock);
+               }
+
                /* checks if there is a pending inactive notification*/
                if (timer->work_pending)
                        timer->delayed_timer_trigger = timer->last_modified_timer;
@@ -372,7 +399,7 @@ static unsigned int idletimer_tg_target(struct sk_buff *skb,
        }
 
        /* TODO: Avoid modifying timers on each packet */
-       reset_timer(info);
+       reset_timer(info, skb);
        return XT_CONTINUE;
 }
 
@@ -400,7 +427,7 @@ static int idletimer_tg_checkentry(const struct xt_tgchk_param *par)
        info->timer = __idletimer_tg_find_by_label(info->label);
        if (info->timer) {
                info->timer->refcnt++;
-               reset_timer(info);
+               reset_timer(info, NULL);
                pr_debug("increased refcnt of timer %s to %u\n",
                         info->label, info->timer->refcnt);
        } else {
index 907214b4c4d071444dbb67ae3cb4559fe3a8267a..fc6cbe8278561a8dd8eeeefadc1a5ae1b5d8f288 100644 (file)
@@ -71,14 +71,14 @@ static ctl_table rds_sysctl_rds_table[] = {
        {
                .procname       = "max_unacked_packets",
                .data           = &rds_sysctl_max_unacked_packets,
-               .maxlen         = sizeof(unsigned long),
+               .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
        {
                .procname       = "max_unacked_bytes",
                .data           = &rds_sysctl_max_unacked_bytes,
-               .maxlen         = sizeof(unsigned long),
+               .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
index 5c8e7cfa9de395d1192c2cc12fae631ae8705a96..f3dbbc0f15dd5d3988fe639ac1fd5c2b38bf2879 100644 (file)
@@ -298,13 +298,15 @@ static void avc_operation_decision_free(
 
 static void avc_operation_free(struct avc_operation_node *ops_node)
 {
-       struct avc_operation_decision_node *od_node;
+       struct avc_operation_decision_node *od_node, *tmp;
 
        if (!ops_node)
                return;
 
-       list_for_each_entry(od_node, &ops_node->od_head, od_list)
+       list_for_each_entry_safe(od_node, tmp, &ops_node->od_head, od_list) {
+               list_del(&od_node->od_list);
                avc_operation_decision_free(od_node);
+       }
        kmem_cache_free(avc_operation_node_cachep, ops_node);
 }
 
index ff427733c2903cab275a05da0887478850e1e374..a96bed4db3e8aa04dc637372be6dff175309d295 100644 (file)
@@ -150,7 +150,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
                goto out;
 
        /* No partial writes. */
-       length = EINVAL;
+       length = -EINVAL;
        if (*ppos != 0)
                goto out;
 
@@ -1190,7 +1190,7 @@ static void sel_remove_entries(struct dentry *de)
        spin_lock(&de->d_lock);
        node = de->d_subdirs.next;
        while (node != &de->d_subdirs) {
-               struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
+               struct dentry *d = list_entry(node, struct dentry, d_child);
 
                spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
                list_del_init(node);
@@ -1664,12 +1664,12 @@ static void sel_remove_classes(void)
 
        list_for_each(class_node, &class_dir->d_subdirs) {
                struct dentry *class_subdir = list_entry(class_node,
-                                       struct dentry, d_u.d_child);
+                                       struct dentry, d_child);
                struct list_head *class_subdir_node;
 
                list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
                        struct dentry *d = list_entry(class_subdir_node,
-                                               struct dentry, d_u.d_child);
+                                               struct dentry, d_child);
 
                        if (d->d_inode)
                                if (d->d_inode->i_mode & S_IFDIR)
index 2e4ff003abcdc137fcb4069c47d83b2d04e16089..dd7466cb2021d969788bfddc555fcebeb05fa68b 100644 (file)
@@ -565,6 +565,9 @@ int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
                return rc;
 
        if (cur->key.specified & AVTAB_OP) {
+               rc = put_entry(&cur->datum.u.ops->type, sizeof(u8), 1, fp);
+               if (rc)
+                       return rc;
                for (i = 0; i < ARRAY_SIZE(cur->datum.u.ops->op.perms); i++)
                        buf32[i] = cpu_to_le32(cur->datum.u.ops->op.perms[i]);
                rc = put_entry(buf32, sizeof(u32),
index 4ff60a6427d9d8d3ea7cf095bc2766f2d49955fc..2e67dd590be54465a0dacd0fe4471e21dc8505ce 100644 (file)
@@ -683,13 +683,8 @@ static int seq_timing_event(unsigned char *event_rec)
                        break;
 
                case TMR_ECHO:
-                       if (seq_mode == SEQ_2)
-                               seq_copy_to_input(event_rec, 8);
-                       else
-                       {
-                               parm = (parm << 8 | SEQ_ECHO);
-                               seq_copy_to_input((unsigned char *) &parm, 4);
-                       }
+                       parm = (parm << 8 | SEQ_ECHO);
+                       seq_copy_to_input((unsigned char *) &parm, 4);
                        break;
 
                default:;
@@ -1332,7 +1327,6 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a
        int mode = translate_mode(file);
        struct synth_info inf;
        struct seq_event_rec event_rec;
-       unsigned long flags;
        int __user *p = arg;
 
        orig_dev = dev = dev >> 4;
@@ -1487,9 +1481,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a
                case SNDCTL_SEQ_OUTOFBAND:
                        if (copy_from_user(&event_rec, arg, sizeof(event_rec)))
                                return -EFAULT;
-                       spin_lock_irqsave(&lock,flags);
                        play_event(event_rec.arr);
-                       spin_unlock_irqrestore(&lock,flags);
                        return 0;
 
                case SNDCTL_MIDI_INFO:
index 8c5010f7889cbd57192cfaa03d77972f7522aded..70e6fe186d3436bbfc6dbbc13d94518a53a48860 100644 (file)
@@ -181,8 +181,10 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
        }
 #endif
  
-       strcpy(card->driver, emu->card_capabilities->driver);
-       strcpy(card->shortname, emu->card_capabilities->name);
+       strlcpy(card->driver, emu->card_capabilities->driver,
+               sizeof(card->driver));
+       strlcpy(card->shortname, emu->card_capabilities->name,
+               sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
                 card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
index 0a34b5f1c47571b6c30ae5c04f53180b1e76e0ef..f8a6549f00e51a0dc13ecd08603707222b3359c2 100644 (file)
@@ -415,7 +415,7 @@ start_voice(struct snd_emux_voice *vp)
        snd_emu10k1_ptr_write(hw, Z2, ch, 0);
 
        /* invalidate maps */
-       temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK;
+       temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
        snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
 #if 0
@@ -436,7 +436,7 @@ start_voice(struct snd_emux_voice *vp)
                snd_emu10k1_ptr_write(hw, CDF, ch, sample);
 
                /* invalidate maps */
-               temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK;
+               temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
                snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
                snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
                
index bdd888ec9a8422838144fd93e8c8b8cff92ee4fe..a131092572e6f75317008f9793e1c8cfa042dd60 100644 (file)
@@ -282,7 +282,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
        snd_emu10k1_ptr_write(emu, TCB, 0, 0);  /* taken from original driver */
        snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
 
-       silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        for (ch = 0; ch < NUM_G; ch++) {
                snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page);
                snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
@@ -348,6 +348,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
        }
 
+       if (emu->address_mode == 0) {
+               /* use 16M in 4G */
+               outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG);
+       }
+
        return 0;
 }
 
@@ -1411,7 +1416,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         *
         */
        {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
-        .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]",
+        .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0108_chip = 1,
@@ -1561,7 +1566,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .adc_1361t = 1,  /* 24 bit capture instead of 16bit */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
-        .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]",
+        .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
@@ -1865,8 +1870,10 @@ int snd_emu10k1_create(struct snd_card *card,
 
        is_audigy = emu->audigy = c->emu10k2_chip;
 
+       /* set addressing mode */
+       emu->address_mode = is_audigy ? 0 : 1;
        /* set the DMA transfer mask */
-       emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
+       emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK;
        if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
            pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
                snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
@@ -1889,7 +1896,7 @@ int snd_emu10k1_create(struct snd_card *card,
 
        emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                               32 * 1024, &emu->ptb_pages) < 0) {
+                               (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) {
                err = -ENOMEM;
                goto error;
        }
@@ -1988,8 +1995,8 @@ int snd_emu10k1_create(struct snd_card *card,
 
        /* Clear silent pages and set up pointers */
        memset(emu->silent_page.area, 0, PAGE_SIZE);
-       silent_page = emu->silent_page.addr << 1;
-       for (idx = 0; idx < MAXPAGES; idx++)
+       silent_page = emu->silent_page.addr << emu->address_mode;
+       for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++)
                ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
 
        /* set up voice indices */
index 5ae1d045bdcb5f0bfad786ab3cc527adbeb3bc86..7581019d7c84c7888b7d053085fbff8c688e389c 100644 (file)
@@ -379,7 +379,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
        snd_emu10k1_ptr_write(emu, Z1, voice, 0);
        snd_emu10k1_ptr_write(emu, Z2, voice, 0);
        /* invalidate maps */
-       silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
        snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
        /* modulation envelope */
index 2ca9f2e93139e125925c096f3e6163c3e2cd1c87..53745f4c2bf59f136ed664edd4276d8ccf5cfa63 100644 (file)
@@ -241,31 +241,22 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
        u32 value2;
-       unsigned long flags;
        u32 rate;
 
        if (emu->card_capabilities->emu_model) {
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, 0x38, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                if ((value & 0x1) == 0) {
-                       spin_lock_irqsave(&emu->emu_lock, flags);
                        snd_emu1010_fpga_read(emu, 0x2a, &value);
                        snd_emu1010_fpga_read(emu, 0x2b, &value2);
-                       spin_unlock_irqrestore(&emu->emu_lock, flags);
                        rate = 0x1770000 / (((value << 5) | value2)+1); 
                        snd_iprintf(buffer, "ADAT Locked : %u\n", rate);
                } else {
                        snd_iprintf(buffer, "ADAT Unlocked\n");
                }
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, 0x20, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                if ((value & 0x4) == 0) {
-                       spin_lock_irqsave(&emu->emu_lock, flags);
                        snd_emu1010_fpga_read(emu, 0x28, &value);
                        snd_emu1010_fpga_read(emu, 0x29, &value2);
-                       spin_unlock_irqrestore(&emu->emu_lock, flags);
                        rate = 0x1770000 / (((value << 5) | value2)+1); 
                        snd_iprintf(buffer, "SPDIF Locked : %d\n", rate);
                } else {
@@ -410,14 +401,11 @@ static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
 {
        struct snd_emu10k1 *emu = entry->private_data;
        u32 value;
-       unsigned long flags;
        int i;
        snd_iprintf(buffer, "EMU1010 Registers:\n\n");
 
        for(i = 0; i < 0x40; i+=1) {
-               spin_lock_irqsave(&emu->emu_lock, flags);
                snd_emu1010_fpga_read(emu, i, &value);
-               spin_unlock_irqrestore(&emu->emu_lock, flags);
                snd_iprintf(buffer, "%02X: %08X, %02X\n", i, value, (value >> 8) & 0x7f);
        }
 }
index ae709c1ab3a848e3b954d7e04747d423b30d1e55..d514458efe3dde8b710cf342c39c8a5831635cfe 100644 (file)
  * aligned pages in others
  */
 #define __set_ptb_entry(emu,page,addr) \
-       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page)))
+       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
 
 #define UNIT_PAGES             (PAGE_SIZE / EMUPAGESIZE)
-#define MAX_ALIGN_PAGES                (MAXPAGES / UNIT_PAGES)
+#define MAX_ALIGN_PAGES0               (MAXPAGES0 / UNIT_PAGES)
+#define MAX_ALIGN_PAGES1               (MAXPAGES1 / UNIT_PAGES)
 /* get aligned page from offset address */
 #define get_aligned_page(offset)       ((offset) >> PAGE_SHIFT)
 /* get offset address from aligned page */
@@ -124,7 +125,7 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis
                }
                page = blk->mapped_page + blk->pages;
        }
-       size = MAX_ALIGN_PAGES - page;
+       size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page;
        if (size >= max_size) {
                *nextp = pos;
                return page;
@@ -181,7 +182,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
                q = get_emu10k1_memblk(p, mapped_link);
                end_page = q->mapped_page;
        } else
-               end_page = MAX_ALIGN_PAGES;
+               end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0);
 
        /* remove links */
        list_del(&blk->mapped_link);
@@ -305,7 +306,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst
        if (snd_BUG_ON(!emu))
                return NULL;
        if (snd_BUG_ON(runtime->dma_bytes <= 0 ||
-                      runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE))
+                      runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE))
                return NULL;
        hdr = emu->memhdr;
        if (snd_BUG_ON(!hdr))
index 83a0f9b4452b2e984d9ee034aa4a574a8b29b601..68261a778ee545a0f52c9a4c29e975d1cd6dacd7 100644 (file)
@@ -2078,6 +2078,16 @@ int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo);
 
+/* meta hook to call each driver's vmaster hook */
+static void vmaster_hook(void *private_data, int enabled)
+{
+       struct hda_vmaster_mute_hook *hook = private_data;
+
+       if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER)
+               enabled = hook->mute_mode;
+       hook->hook(hook->codec, enabled);
+}
+
 /**
  * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
  * @codec: HD-audio codec
@@ -2772,9 +2782,9 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec,
 
        if (!hook->hook || !hook->sw_kctl)
                return 0;
-       snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
        hook->codec = codec;
        hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+       snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook);
        if (!expose_enum_ctl)
                return 0;
        kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
@@ -2797,14 +2807,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
         */
        if (hook->codec->bus->shutdown)
                return;
-       switch (hook->mute_mode) {
-       case HDA_VMUTE_FOLLOW_MASTER:
-               snd_ctl_sync_vmaster_hook(hook->sw_kctl);
-               break;
-       default:
-               hook->hook(hook->codec, hook->mute_mode);
-               break;
-       }
+       snd_ctl_sync_vmaster_hook(hook->sw_kctl);
 }
 EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
 
index 4008034b6ebed9449e038e189b37e82f4c56d093..a8eb7fe2766e1c9a3e7998ce1029cd76ef1d1443 100644 (file)
@@ -266,7 +266,7 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
 {
        /* We currently only handle front, HP */
        static hda_nid_t pins[] = {
-               0x0f, 0x10, 0x14, 0x15, 0
+               0x0f, 0x10, 0x14, 0x15, 0x17, 0
        };
        hda_nid_t *p;
        for (p = pins; *p; p++)
@@ -3363,6 +3363,7 @@ enum {
        ALC269_FIXUP_QUANTA_MUTE,
        ALC269_FIXUP_LIFEBOOK,
        ALC269_FIXUP_LIFEBOOK_EXTMIC,
+       ALC269_FIXUP_LIFEBOOK_HP_PIN,
        ALC269_FIXUP_AMIC,
        ALC269_FIXUP_DMIC,
        ALC269VB_FIXUP_AMIC,
@@ -3477,6 +3478,13 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                },
        },
+       [ALC269_FIXUP_LIFEBOOK_HP_PIN] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x21, 0x0221102f }, /* HP out */
+                       { }
+               },
+       },
        [ALC269_FIXUP_AMIC] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -3727,6 +3735,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
        SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
+       SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN),
        SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
index 319754cf62086ef86723a9df60c236d31edfab16..daf61abc3670f5d243040a53b3520cb9f1419764 100644 (file)
@@ -118,12 +118,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (snd_BUG_ON(!arg || !emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
-
-       if (!snd_emux_inc_count(emu)) {
-               mutex_unlock(&emu->register_mutex);
+       if (!snd_emux_inc_count(emu))
                return -EFAULT;
-       }
 
        memset(&callback, 0, sizeof(callback));
        callback.owner = THIS_MODULE;
@@ -135,7 +131,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (p == NULL) {
                snd_printk(KERN_ERR "can't create port\n");
                snd_emux_dec_count(emu);
-               mutex_unlock(&emu->register_mutex);
                return -ENOMEM;
        }
 
@@ -148,8 +143,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        reset_port_mode(p, arg->seq_mode);
 
        snd_emux_reset_port(p);
-
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
@@ -195,13 +188,11 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg)
        if (snd_BUG_ON(!emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
        snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port));
        snd_seq_event_port_detach(p->chset.client, p->chset.port);
        snd_emux_dec_count(emu);
 
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
index 7778b8e19782e24a3ca56a5aa5dff9e00bf33e4d..a0209204ae4892a490877c30eaf056c45cd8043a 100644 (file)
@@ -124,12 +124,10 @@ snd_emux_detach_seq(struct snd_emux *emu)
        if (emu->voices)
                snd_emux_terminate_all(emu);
                
-       mutex_lock(&emu->register_mutex);
        if (emu->client >= 0) {
                snd_seq_delete_kernel_client(emu->client);
                emu->client = -1;
        }
-       mutex_unlock(&emu->register_mutex);
 }
 
 
@@ -269,8 +267,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data,
 /*
  * increment usage count
  */
-int
-snd_emux_inc_count(struct snd_emux *emu)
+static int
+__snd_emux_inc_count(struct snd_emux *emu)
 {
        emu->used++;
        if (!try_module_get(emu->ops.owner))
@@ -284,12 +282,21 @@ snd_emux_inc_count(struct snd_emux *emu)
        return 1;
 }
 
+int snd_emux_inc_count(struct snd_emux *emu)
+{
+       int ret;
+
+       mutex_lock(&emu->register_mutex);
+       ret = __snd_emux_inc_count(emu);
+       mutex_unlock(&emu->register_mutex);
+       return ret;
+}
 
 /*
  * decrease usage count
  */
-void
-snd_emux_dec_count(struct snd_emux *emu)
+static void
+__snd_emux_dec_count(struct snd_emux *emu)
 {
        module_put(emu->card->module);
        emu->used--;
@@ -298,6 +305,12 @@ snd_emux_dec_count(struct snd_emux *emu)
        module_put(emu->ops.owner);
 }
 
+void snd_emux_dec_count(struct snd_emux *emu)
+{
+       mutex_lock(&emu->register_mutex);
+       __snd_emux_dec_count(emu);
+       mutex_unlock(&emu->register_mutex);
+}
 
 /*
  * Routine that is called upon a first use of a particular port
@@ -317,7 +330,7 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_init_port(p);
-       snd_emux_inc_count(emu);
+       __snd_emux_inc_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
@@ -340,7 +353,7 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
-       snd_emux_dec_count(emu);
+       __snd_emux_dec_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
index c89a5bf5c00e6b3dccf2741ef7b20b4253ac91b1..c311681bd3900c0cdd404e6adf9a5ec8b6de7f31 100644 (file)
@@ -175,6 +175,7 @@ static const struct rc_config {
        { USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
        { USB_ID(0x041e, 0x3042), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 */
        { USB_ID(0x041e, 0x30df), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
+       { USB_ID(0x041e, 0x3237), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
        { USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
 };
 
index 970ac6946150905d164af642eeddb571e6c95d77..c5c8bdc1ff29025650585e1fa1c8c02178ad4bac 100644 (file)
@@ -1,13 +1,16 @@
 LOCAL_PATH := $(call my-dir)
+
+# Don't use this file if GATOR_DAEMON_PATH is set and we're not under that path
+ifneq ($(and $(GATOR_DAEMON_PATH),$(filter $(patsubst %/,%,$(GATOR_DAEMON_PATH))/%,$(LOCAL_PATH)/)),)
+
 include $(CLEAR_VARS)
 
-XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h)
+XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h SrcMd5.cpp)
 
 LOCAL_SRC_FILES := \
        AnnotateListener.cpp \
        Buffer.cpp \
        CCNDriver.cpp \
-       CPUFreqDriver.cpp \
        CapturedXML.cpp \
        Child.cpp \
        Command.cpp \
@@ -43,6 +46,7 @@ LOCAL_SRC_FILES := \
        SessionXML.cpp \
        Setup.cpp \
        Source.cpp \
+       SrcMd5.cpp \
        StreamlineSetup.cpp \
        UEvent.cpp \
        UserSpaceSource.cpp \
@@ -74,3 +78,5 @@ LOCAL_MODULE := gatord
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
+
+endif
index 50110b4dc84c40b120f5506cf4e16f69e36c17ac..5966cbea8d13620fc684252f8e07d452411d76e0 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
 
 #include "OlySocket.h"
 
+static const char STREAMLINE_ANNOTATE_PARENT[] = "\0streamline-annotate-parent";
+
 struct AnnotateClient {
        AnnotateClient *next;
        int fd;
 };
 
-AnnotateListener::AnnotateListener() : mClients(NULL), mSock(NULL) {
+AnnotateListener::AnnotateListener() : mClients(NULL), mSock(NULL), mUds(NULL) {
 }
 
 AnnotateListener::~AnnotateListener() {
        close();
+       delete mUds;
        delete mSock;
 }
 
 void AnnotateListener::setup() {
        mSock = new OlyServerSocket(8082);
+       mUds = new OlyServerSocket(STREAMLINE_ANNOTATE_PARENT, sizeof(STREAMLINE_ANNOTATE_PARENT), true);
 }
 
-int AnnotateListener::getFd() {
+int AnnotateListener::getSockFd() {
        return mSock->getFd();
 }
 
-void AnnotateListener::handle() {
+void AnnotateListener::handleSock() {
        AnnotateClient *const client = new AnnotateClient();
        client->fd = mSock->acceptConnection();
        client->next = mClients;
        mClients = client;
 }
 
+int AnnotateListener::getUdsFd() {
+       return mUds->getFd();
+}
+
+void AnnotateListener::handleUds() {
+       AnnotateClient *const client = new AnnotateClient();
+       client->fd = mUds->acceptConnection();
+       client->next = mClients;
+       mClients = client;
+}
+
 void AnnotateListener::close() {
-       mSock->closeServerSocket();
+       if (mUds != NULL) {
+               mUds->closeServerSocket();
+       }
+       if (mSock != NULL) {
+               mSock->closeServerSocket();
+       }
        while (mClients != NULL) {
                ::close(mClients->fd);
                AnnotateClient *next = mClients->next;
index cdefef12db224a506cdbf10731e580fa733a55cf..6bc747d42d18081dc49da93a1e037d97e860f5f4 100644 (file)
@@ -1,12 +1,15 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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.
  */
 
-class AnnotateClient;
+#ifndef ANNOTATELISTENER_H
+#define ANNOTATELISTENER_H
+
+struct AnnotateClient;
 class OlyServerSocket;
 
 class AnnotateListener {
@@ -15,17 +18,22 @@ public:
        ~AnnotateListener();
 
        void setup();
-       int getFd();
+       int getSockFd();
+       int getUdsFd();
 
-       void handle();
+       void handleSock();
+       void handleUds();
        void close();
        void signal();
 
 private:
        AnnotateClient *mClients;
        OlyServerSocket *mSock;
+       OlyServerSocket *mUds;
 
        // Intentionally unimplemented
        AnnotateListener(const AnnotateListener &);
        AnnotateListener &operator=(const AnnotateListener &);
 };
+
+#endif // ANNOTATELISTENER_H
index 3ada471cac19eeebb9a53d7cc36a7bc423c4be52..8b0a7882e938ac4faddc88c2e4a645346facfcaf 100644 (file)
@@ -1,3 +1,3 @@
-APP_PLATFORM := android-8
+APP_PLATFORM := android-9
 # Replace armeabi-v7a with arm64-v8a to build an arm64 gatord or with armeabi to build an ARM11 gatord
 APP_ABI := armeabi-v7a
index 8fa6280150694d1b681a209d5f1eded1930a4686..c4ced9f607f902587a53089ed2bf9846b7a51c82 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
 #include "SessionData.h"
 
 #define mask (mSize - 1)
+#define FRAME_HEADER_SIZE 3
 
 enum {
-       CODE_PEA         = 1,
-       CODE_KEYS        = 2,
-       CODE_FORMAT      = 3,
-       CODE_MAPS        = 4,
-       CODE_COMM        = 5,
-       CODE_KEYS_OLD    = 6,
-       CODE_ONLINE_CPU  = 7,
-       CODE_OFFLINE_CPU = 8,
-       CODE_KALLSYMS    = 9,
+       CODE_PEA         =  1,
+       CODE_KEYS        =  2,
+       CODE_FORMAT      =  3,
+       CODE_MAPS        =  4,
+       CODE_COMM        =  5,
+       CODE_KEYS_OLD    =  6,
+       CODE_ONLINE_CPU  =  7,
+       CODE_OFFLINE_CPU =  8,
+       CODE_KALLSYMS    =  9,
+       CODE_COUNTERS    = 10,
 };
 
 // Summary Frame Messages
@@ -47,7 +49,7 @@ enum {
 
 Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mBuf(new char[size]), mReaderSem(readerSem), mCommitTime(gSessionData->mLiveRate), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mCore(core), mBufType(buftype) {
        if ((mSize & mask) != 0) {
-               logg->logError(__FILE__, __LINE__, "Buffer size is not a power of 2");
+               logg->logError("Buffer size is not a power of 2");
                handleException();
        }
        sem_init(&mWriterSem, 0, 0);
@@ -141,7 +143,7 @@ int Buffer::contiguousSpaceAvailable() const {
        }
 }
 
-void Buffer::commit(const uint64_t time) {
+void Buffer::commit(const uint64_t time, const bool force) {
        // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload
        const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
        int length = mWritePos - mCommitPos;
@@ -149,6 +151,10 @@ void Buffer::commit(const uint64_t time) {
                length += mSize;
        }
        length = length - typeLength - sizeof(int32_t);
+       if (!force && !mIsDone && length <= FRAME_HEADER_SIZE) {
+               // Nothing to write, only the frame header is present
+               return;
+       }
        for (size_t byte = 0; byte < sizeof(int32_t); byte++) {
                mBuf[(mCommitPos + typeLength + byte) & mask] = (length >> byte * 8) & 0xFF;
        }
@@ -317,7 +323,7 @@ void Buffer::event64(const int key, const int64_t value) {
        }
 }
 
-void Buffer::pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key) {
+void Buffer::marshalPea(const uint64_t currTime, const struct perf_event_attr *const pea, int key) {
        while (!checkSpace(2 * MAXSIZE_PACK32 + pea->size)) {
                sem_wait(&mWriterSem);
        }
@@ -327,7 +333,7 @@ void Buffer::pea(const uint64_t currTime, const struct perf_event_attr *const pe
        check(currTime);
 }
 
-void Buffer::keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys) {
+void Buffer::marshalKeys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys) {
        while (!checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) {
                sem_wait(&mWriterSem);
        }
@@ -340,7 +346,7 @@ void Buffer::keys(const uint64_t currTime, const int count, const __u64 *const i
        check(currTime);
 }
 
-void Buffer::keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf) {
+void Buffer::marshalKeysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf) {
        while (!checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) {
                sem_wait(&mWriterSem);
        }
@@ -353,7 +359,7 @@ void Buffer::keysOld(const uint64_t currTime, const int keyCount, const int *con
        check(currTime);
 }
 
-void Buffer::format(const uint64_t currTime, const int length, const char *const format) {
+void Buffer::marshalFormat(const uint64_t currTime, const int length, const char *const format) {
        while (!checkSpace(MAXSIZE_PACK32 + length + 1)) {
                sem_wait(&mWriterSem);
        }
@@ -362,7 +368,7 @@ void Buffer::format(const uint64_t currTime, const int length, const char *const
        check(currTime);
 }
 
-void Buffer::maps(const uint64_t currTime, const int pid, const int tid, const char *const maps) {
+void Buffer::marshalMaps(const uint64_t currTime, const int pid, const int tid, const char *const maps) {
        const int mapsLen = strlen(maps) + 1;
        while (!checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) {
                sem_wait(&mWriterSem);
@@ -374,7 +380,7 @@ void Buffer::maps(const uint64_t currTime, const int pid, const int tid, const c
        check(currTime);
 }
 
-void Buffer::comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm) {
+void Buffer::marshalComm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm) {
        const int imageLen = strlen(image) + 1;
        const int commLen = strlen(comm) + 1;
        while (!checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) {
@@ -388,27 +394,27 @@ void Buffer::comm(const uint64_t currTime, const int pid, const int tid, const c
        check(currTime);
 }
 
-void Buffer::onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) {
+void Buffer::onlineCPU(const uint64_t currTime, const int cpu) {
        while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
                sem_wait(&mWriterSem);
        }
        packInt(CODE_ONLINE_CPU);
-       packInt64(time);
+       packInt64(currTime);
        packInt(cpu);
        check(currTime);
 }
 
-void Buffer::offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) {
+void Buffer::offlineCPU(const uint64_t currTime, const int cpu) {
        while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
                sem_wait(&mWriterSem);
        }
        packInt(CODE_OFFLINE_CPU);
-       packInt64(time);
+       packInt64(currTime);
        packInt(cpu);
        check(currTime);
 }
 
-void Buffer::kallsyms(const uint64_t currTime, const char *const kallsyms) {
+void Buffer::marshalKallsyms(const uint64_t currTime, const char *const kallsyms) {
        const int kallsymsLen = strlen(kallsyms) + 1;
        while (!checkSpace(3 * MAXSIZE_PACK32 + kallsymsLen)) {
                sem_wait(&mWriterSem);
@@ -418,6 +424,31 @@ void Buffer::kallsyms(const uint64_t currTime, const char *const kallsyms) {
        check(currTime);
 }
 
+void Buffer::perfCounterHeader(const uint64_t time) {
+       while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+               sem_wait(&mWriterSem);
+       }
+       packInt(CODE_COUNTERS);
+       packInt64(time);
+}
+
+void Buffer::perfCounter(const int core, const int key, const int64_t value) {
+       while (!checkSpace(2*MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+               sem_wait(&mWriterSem);
+       }
+       packInt(core);
+       packInt(key);
+       packInt64(value);
+}
+
+void Buffer::perfCounterFooter(const uint64_t currTime) {
+       while (!checkSpace(MAXSIZE_PACK32)) {
+               sem_wait(&mWriterSem);
+       }
+       packInt(-1);
+       check(currTime);
+}
+
 void Buffer::setDone() {
        mIsDone = true;
        commit(0);
index 6cffd8e39a36748d9b2a447bb46ebaff926b662c..13c44e1fd3594747ed3d0692133a498429b0921d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -36,7 +36,7 @@ public:
 
        int bytesAvailable() const;
        int contiguousSpaceAvailable() const;
-       void commit(const uint64_t time);
+       void commit(const uint64_t time, const bool force = false);
        void check(const uint64_t time);
 
        // Summary messages
@@ -50,15 +50,18 @@ public:
        void event64(int key, int64_t value);
 
        // Perf Attrs messages
-       void pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key);
-       void keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys);
-       void keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf);
-       void format(const uint64_t currTime, const int length, const char *const format);
-       void maps(const uint64_t currTime, const int pid, const int tid, const char *const maps);
-       void comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm);
-       void onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu);
-       void offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu);
-       void kallsyms(const uint64_t currTime, const char *const kallsyms);
+       void marshalPea(const uint64_t currTime, const struct perf_event_attr *const pea, int key);
+       void marshalKeys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys);
+       void marshalKeysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf);
+       void marshalFormat(const uint64_t currTime, const int length, const char *const format);
+       void marshalMaps(const uint64_t currTime, const int pid, const int tid, const char *const maps);
+       void marshalComm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm);
+       void onlineCPU(const uint64_t currTime, const int cpu);
+       void offlineCPU(const uint64_t currTime, const int cpu);
+       void marshalKallsyms(const uint64_t currTime, const char *const kallsyms);
+       void perfCounterHeader(const uint64_t time);
+       void perfCounter(const int core, const int key, const int64_t value);
+       void perfCounterFooter(const uint64_t currTime);
 
        void setDone();
        bool isDone() const;
index dd1a2b1338429eb3ed41c3bbd6b3a633d8487e44..d77513acc4e42e82c01e8dec78aedc55dc161d34 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -28,7 +28,6 @@ static const char TAG_OPTION_SET[] = "option_set";
 
 static const char ATTR_AVERAGE_SELECTION[] = "average_selection";
 static const char ATTR_COUNTER[] = "counter";
-static const char ATTR_COUNTER_SET[] = "counter_set";
 static const char ATTR_COUNT[] = "count";
 static const char ATTR_DESCRIPTION[] = "description";
 static const char ATTR_DISPLAY[] = "display";
@@ -110,7 +109,7 @@ void CCNDriver::readEvents(mxml_node_t *const) {
 
        int type;
        if (DriverSource::readIntDriver("/sys/bus/event_source/devices/ccn/type", &type) != 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to read CCN-5xx type");
+               logg->logError("Unable to read CCN-5xx type");
                handleException();
        }
 
index fb4c717e969a59a5199c8a2bdbd46fcda6cae9f5..06ac33f07a36c7ef6b0b0fe5452a6cfefa9e6578 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
diff --git a/tools/gator/daemon/COPYING b/tools/gator/daemon/COPYING
new file mode 100644 (file)
index 0000000..d159169
--- /dev/null
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/tools/gator/daemon/CPUFreqDriver.cpp b/tools/gator/daemon/CPUFreqDriver.cpp
deleted file mode 100644 (file)
index 41f9d6f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "CPUFreqDriver.h"
-
-#include "Buffer.h"
-#include "DriverSource.h"
-#include "Logging.h"
-#include "SessionData.h"
-
-CPUFreqDriver::CPUFreqDriver() : mPrev() {
-}
-
-CPUFreqDriver::~CPUFreqDriver() {
-}
-
-void CPUFreqDriver::readEvents(mxml_node_t *const) {
-       // Only for use with perf
-       if (!gSessionData->perf.isSetup()) {
-               return;
-       }
-
-       setCounters(new DriverCounter(getCounters(), strdup("Linux_power_cpu_freq")));
-}
-
-void CPUFreqDriver::read(Buffer *const buffer) {
-       char buf[64];
-       const DriverCounter *const counter = getCounters();
-       if ((counter == NULL) || !counter->isEnabled()) {
-               return;
-       }
-
-       const int key = getCounters()->getKey();
-       bool resetCores = false;
-       for (int i = 0; i < gSessionData->mCores; ++i) {
-               snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/cpufreq/cpuinfo_cur_freq", i);
-               int64_t freq;
-               if (DriverSource::readInt64Driver(buf, &freq) != 0) {
-                       freq = 0;
-               }
-               if (mPrev[i] != freq) {
-                       mPrev[i] = freq;
-                       // Change cores
-                       buffer->event64(2, i);
-                       resetCores = true;
-                       buffer->event64(key, 1000*freq);
-               }
-       }
-       if (resetCores) {
-               // Revert cores, UserSpaceSource is all on core 0
-               buffer->event64(2, 0);
-       }
-}
diff --git a/tools/gator/daemon/CPUFreqDriver.h b/tools/gator/daemon/CPUFreqDriver.h
deleted file mode 100644 (file)
index ad8c9aa..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef CPUFREQDRIVER_H
-#define CPUFREQDRIVER_H
-
-#include "Config.h"
-#include "Driver.h"
-
-class CPUFreqDriver : public PolledDriver {
-private:
-       typedef PolledDriver super;
-
-public:
-       CPUFreqDriver();
-       ~CPUFreqDriver();
-
-       void readEvents(mxml_node_t *const root);
-       void read(Buffer *const buffer);
-
-private:
-       int64_t mPrev[NR_CPUS];
-
-       // Intentionally unimplemented
-       CPUFreqDriver(const CPUFreqDriver &);
-       CPUFreqDriver &operator=(const CPUFreqDriver &);
-};
-
-#endif // CPUFREQDRIVER_H
index 0b5802c893bbbfe10573041bfe26a1141ed6e8a4..1854c77dcb0eb709438b830a32481015d52cb86e 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -34,7 +34,6 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) {
        mxmlElementSetAttr(captured, "version", "1");
        if (gSessionData->perf.isSetup()) {
                mxmlElementSetAttr(captured, "type", "Perf");
-               mxmlElementSetAttr(captured, "perf_beta", "yes");
        }
        mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
        if (includeTime) { // Send the following only after the capture is complete
@@ -98,7 +97,7 @@ void CapturedXML::write(char* path) {
 
        char* xml = getXML(true);
        if (util->writeToDisk(file, xml) < 0) {
-               logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
+               logg->logError("Error writing %s\nPlease verify the path.", file);
                handleException();
        }
 
index b704f6e53bb593bcca46326b4a87b1525e4bc04c..69d80c09b514292d0a9221f6f5d5a87dad1f0d6c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 6b5bbb3bf6afb8c727809b56313de32080ae0a69..a19e9cf86805661255d47e4c387a523f69c62022 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -150,13 +150,12 @@ static void *senderThread(void *) {
        prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0);
        sem_wait(&haltPipeline);
 
-       while (!primarySource->isDone() ||
-              !externalSource->isDone() ||
+       while (!externalSource->isDone() ||
               (userSpaceSource != NULL && !userSpaceSource->isDone()) ||
-              (ftraceSource != NULL && !ftraceSource->isDone())) {
+                  (ftraceSource != NULL && !ftraceSource->isDone()) ||
+              !primarySource->isDone()) {
                sem_wait(&senderSem);
 
-               primarySource->write(sender);
                externalSource->write(sender);
                if (userSpaceSource != NULL) {
                        userSpaceSource->write(sender);
@@ -164,6 +163,7 @@ static void *senderThread(void *) {
                if (ftraceSource != NULL) {
                        ftraceSource->write(sender);
                }
+               primarySource->write(sender);
        }
 
        // write end-of-capture sequence
@@ -232,7 +232,7 @@ void Child::run() {
        sender = new Sender(socket);
 
        if (mNumConnections > 1) {
-               logg->logError(__FILE__, __LINE__, "Session already in progress");
+               logg->logError("Session already in progress");
                handleException();
        }
 
@@ -267,7 +267,7 @@ void Child::run() {
                char* xmlString;
                xmlString = util->readFromDisk(gSessionData->mSessionXMLPath);
                if (xmlString == 0) {
-                       logg->logError(__FILE__, __LINE__, "Unable to read session xml file: %s", gSessionData->mSessionXMLPath);
+                       logg->logError("Unable to read session xml file: %s", gSessionData->mSessionXMLPath);
                        handleException();
                }
                gSessionData->parseSessionXML(xmlString);
@@ -280,16 +280,27 @@ void Child::run() {
        }
 
        if (gSessionData->kmod.isMaliCapture() && (gSessionData->mSampleRate == 0)) {
-               logg->logError(__FILE__, __LINE__, "Mali counters are not supported with Sample Rate: None.");
+               logg->logError("Mali counters are not supported with Sample Rate: None.");
                handleException();
        }
 
+       // Initialize ftrace source before child as it's slow and dependens on nothing else
+       // If initialized later, us gator with ftrace has time sync issues
+       if (gSessionData->ftraceDriver.countersEnabled()) {
+               ftraceSource = new FtraceSource(&senderSem);
+               if (!ftraceSource->prepare()) {
+                       logg->logError("Unable to prepare userspace source for capture");
+                       handleException();
+               }
+               ftraceSource->start();
+       }
+
        // Must be after session XML is parsed
        if (!primarySource->prepare()) {
                if (gSessionData->perf.isSetup()) {
-                       logg->logError(__FILE__, __LINE__, "Unable to prepare gator driver for capture");
+                       logg->logError("Unable to communicate with the perf API, please ensure that CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER are enabled. Please refer to README_Streamline.txt for more information.");
                } else {
-                       logg->logError(__FILE__, __LINE__, "Unable to communicate with the perf API, please ensure that CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER are enabled. Please refer to README_Streamline.txt for more information.");
+                       logg->logError("Unable to prepare gator driver for capture");
                }
                handleException();
        }
@@ -300,7 +311,7 @@ void Child::run() {
        // Must be initialized before senderThread is started as senderThread checks externalSource
        externalSource = new ExternalSource(&senderSem);
        if (!externalSource->prepare()) {
-               logg->logError(__FILE__, __LINE__, "Unable to prepare external source for capture");
+               logg->logError("Unable to prepare external source for capture");
                handleException();
        }
        externalSource->start();
@@ -324,21 +335,12 @@ void Child::run() {
        if (startUSSource) {
                userSpaceSource = new UserSpaceSource(&senderSem);
                if (!userSpaceSource->prepare()) {
-                       logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture");
+                       logg->logError("Unable to prepare userspace source for capture");
                        handleException();
                }
                userSpaceSource->start();
        }
 
-       if (gSessionData->ftraceDriver.countersEnabled()) {
-               ftraceSource = new FtraceSource(&senderSem);
-               if (!ftraceSource->prepare()) {
-                       logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture");
-                       handleException();
-               }
-               ftraceSource->start();
-       }
-
        if (gSessionData->mAllowCommands && (gSessionData->mCaptureCommand != NULL)) {
                pthread_t thread;
                if (pthread_create(&thread, NULL, commandThread, NULL)) {
@@ -347,7 +349,7 @@ void Child::run() {
        }
 
        if (!thread_creation_success) {
-               logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
+               logg->logError("Failed to create gator threads");
                handleException();
        }
 
@@ -357,6 +359,7 @@ void Child::run() {
        // Start profiling
        primarySource->run();
 
+       // Wait for the other threads to exit
        if (ftraceSource != NULL) {
                ftraceSource->join();
        }
@@ -364,8 +367,6 @@ void Child::run() {
                userSpaceSource->join();
        }
        externalSource->join();
-
-       // Wait for the other threads to exit
        pthread_join(senderThreadID, NULL);
 
        // Shutting down the connection should break the stop thread which is stalling on the socket recv() function
index cc78202ceb5caaba8996a92409e7a4fc31cce0c2..a6c54db70a70103abca4b97119d9368cce7d7662 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 28d73cf5a905ae9d75a3553162a6f2fe0429a6e0..0a6e3b9901eed43e6c746ad08c18c30e54601165 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -39,7 +39,7 @@ static int getUid(const char *const name, char *const shPath, const char *const
 
        const int pid = fork();
        if (pid < 0) {
-               logg->logError(__FILE__, __LINE__, "fork failed");
+               logg->logError("fork failed");
                handleException();
        }
        if (pid == 0) {
@@ -94,7 +94,7 @@ void *commandThread(void *) {
        const char *const name = gSessionData->mCaptureUser == NULL ? "nobody" : gSessionData->mCaptureUser;
        const int uid = getUid(name);
        if (uid < 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to lookup the user %s, please double check that the user exists", name);
+               logg->logError("Unable to look up the user %s, please double check that the user exists", name);
                handleException();
        }
 
@@ -103,13 +103,13 @@ void *commandThread(void *) {
        char buf[128];
        int pipefd[2];
        if (pipe_cloexec(pipefd) != 0) {
-               logg->logError(__FILE__, __LINE__, "pipe failed");
+               logg->logError("pipe failed");
                handleException();
        }
 
        const int pid = fork();
        if (pid < 0) {
-               logg->logError(__FILE__, __LINE__, "fork failed");
+               logg->logError("fork failed");
                handleException();
        }
        if (pid == 0) {
@@ -163,7 +163,7 @@ void *commandThread(void *) {
        close(pipefd[1]);
        const ssize_t bytes = read(pipefd[0], buf, sizeof(buf));
        if (bytes > 0) {
-               logg->logError(__FILE__, __LINE__, buf);
+               logg->logError("%s", buf);
                handleException();
        }
        close(pipefd[0]);
index 17244b7aaebcc1ccfffa30a8404eb7870e0ebb98..2838adcec66177ff5e087aa8c908ced0c00f6478 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
index bee383a1c797054cb95af2e2817ba96293dd2369..eb31556e6426a89bb2c2c185d8d8167b6b172fed 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 6590dd38919627fdc20fb335b3e7b3cade55f986..be224a4f2b1f7d453a5704d06e28b23ace61eb25 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -106,7 +106,7 @@ void ConfigurationXML::validate(void) {
                const Counter & counter = gSessionData->mCounters[i];
                if (counter.isEnabled()) {
                        if (strcmp(counter.getType(), "") == 0) {
-                               logg->logError(__FILE__, __LINE__, "Invalid required attribute in configuration.xml:\n  counter=\"%s\"\n  event=%d\n", counter.getType(), counter.getEvent());
+                               logg->logError("Invalid required attribute in configuration.xml:\n  counter=\"%s\"\n  event=%d\n", counter.getType(), counter.getEvent());
                                handleException();
                        }
 
@@ -116,7 +116,7 @@ void ConfigurationXML::validate(void) {
                                if (counter2.isEnabled()) {
                                        // check if the types are the same
                                        if (strcmp(counter.getType(), counter2.getType()) == 0) {
-                                               logg->logError(__FILE__, __LINE__, "Duplicate performance counter type in configuration.xml: %s", counter.getType());
+                                               logg->logError("Duplicate performance counter type in configuration.xml: %s", counter.getType());
                                                handleException();
                                        }
                                }
@@ -169,7 +169,7 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) {
        for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
                if (driver->claimCounter(counter)) {
                        if (counter.getDriver() != NULL) {
-                               logg->logError(__FILE__, __LINE__, "More than one driver has claimed %s:%i", counter.getType(), counter.getEvent());
+                               logg->logError("More than one driver has claimed %s:%i", counter.getType(), counter.getEvent());
                                handleException();
                        }
                        counter.setDriver(driver);
@@ -210,7 +210,7 @@ void ConfigurationXML::remove() {
        getPath(path);
 
        if (::remove(path) != 0) {
-               logg->logError(__FILE__, __LINE__, "Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk");
+               logg->logError("Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk");
                handleException();
        }
        logg->logMessage("Invalid configuration.xml file detected and removed");
index efa415e508b6fd17c78250160ebcd0621f895668..a986ce99381bdc71a3a6afdb7530c6bb0236eed4 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 5202aa04636248754909873776f3c81f6b67269c..a4c22f5713425edf00ef4d633aeeb543f602679d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 5deb0f375f3a4c937789b9bf0741ea96499bebb4..af62bb9a95bd27393812af43d9be0755490f9bc2 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -67,7 +67,7 @@ void DiskIODriver::doRead() {
        }
 
        if (!mBuf.read("/proc/diskstats")) {
-               logg->logError(__FILE__, __LINE__, "Unable to read /proc/diskstats");
+               logg->logError("Unable to read /proc/diskstats");
                handleException();
        }
 
@@ -76,9 +76,9 @@ void DiskIODriver::doRead() {
 
        char *lastName = NULL;
        int lastNameLen = -1;
-       char *start = mBuf.getBuf();
-       while (*start != '\0') {
-               char *end = strchr(start, '\n');
+       char *line = mBuf.getBuf();
+       while (*line != '\0') {
+               char *end = strchr(line, '\n');
                if (end != NULL) {
                        *end = '\0';
                }
@@ -87,15 +87,15 @@ void DiskIODriver::doRead() {
                int nameEnd = -1;
                int64_t readBytes = -1;
                int64_t writeBytes = -1;
-               const int count = sscanf(start, "%*d %*d %n%*s%n %*u %*u %" SCNu64 " %*u %*u %*u %" SCNu64, &nameStart, &nameEnd, &readBytes, &writeBytes);
+               const int count = sscanf(line, "%*d %*d %n%*s%n %*u %*u %" SCNu64 " %*u %*u %*u %" SCNu64, &nameStart, &nameEnd, &readBytes, &writeBytes);
                if (count != 2) {
-                       logg->logError(__FILE__, __LINE__, "Unable to parse /proc/diskstats");
+                       logg->logError("Unable to parse /proc/diskstats");
                        handleException();
                }
 
                // Skip partitions which are identified if the name is a substring of the last non-partition
-               if ((lastName == NULL) || (strncmp(lastName, start + nameStart, lastNameLen) != 0)) {
-                       lastName = start + nameStart;
+               if ((lastName == NULL) || (strncmp(lastName, line + nameStart, lastNameLen) != 0)) {
+                       lastName = line + nameStart;
                        lastNameLen = nameEnd - nameStart;
                        mReadBytes += readBytes;
                        mWriteBytes += writeBytes;
@@ -104,7 +104,7 @@ void DiskIODriver::doRead() {
                if (end == NULL) {
                        break;
                }
-               start = end + 1;
+               line = end + 1;
        }
 }
 
index d0db18c77d04d344871c75bdfea25168fa871e7e..6ecda5afc25a0fa3e4129f79da4ea451b9ca4168 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 275da31c7a0d9d266a4d8e3865b0c9f8802b84c0..72c731424bde40c9cf80548136e8c641ff88c8f8 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 72870e3dbca1a9ec99aa31686e43587d314ad4da..19ec12775a394bded3afdd01244de498e700be7a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 7f299b646952c101c511d59f4985d0bc4fcf6775..34920cee92fb0d8eeeb123f606f4ea1e28357269 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -32,7 +32,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL
 
        mBuffer = new Buffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem);
        if (readIntDriver("/dev/gator/version", &driver_version) == -1) {
-               logg->logError(__FILE__, __LINE__, "Error reading gator driver version");
+               logg->logError("Error reading gator driver version");
                handleException();
        }
 
@@ -40,7 +40,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL
        if (driver_version != PROTOCOL_VERSION) {
                if ((driver_version > PROTOCOL_DEV) || (PROTOCOL_VERSION > PROTOCOL_DEV)) {
                        // One of the mismatched versions is development version
-                       logg->logError(__FILE__, __LINE__,
+                       logg->logError(
                                "DEVELOPMENT BUILD MISMATCH: gator driver version \"%d\" is not in sync with gator daemon version \"%d\".\n"
                                ">> The following must be synchronized from engineering repository:\n"
                                ">> * gator driver\n"
@@ -49,7 +49,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL
                        handleException();
                } else {
                        // Release version mismatch
-                       logg->logError(__FILE__, __LINE__,
+                       logg->logError(
                                "gator driver version \"%d\" is different than gator daemon version \"%d\".\n"
                                ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION);
                        handleException();
@@ -58,7 +58,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL
 
        int enable = -1;
        if (readIntDriver("/dev/gator/enable", &enable) != 0 || enable != 0) {
-               logg->logError(__FILE__, __LINE__, "Driver already enabled, possibly a session is already in progress.");
+               logg->logError("Driver already enabled, possibly a session is already in progress.");
                handleException();
        }
 
@@ -68,7 +68,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL
        }
 
        if (readIntDriver("/dev/gator/buffer_size", &mBufferSize) || mBufferSize <= 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to read the driver buffer size");
+               logg->logError("Unable to read the driver buffer size");
                handleException();
        }
 }
@@ -99,10 +99,11 @@ void DriverSource::bootstrapThread() {
        DynBuf printb;
        DynBuf b1;
        DynBuf b2;
-       const uint64_t currTime = getTime();
+       // MonotonicStarted may not be not assigned yet
+       const uint64_t currTime = 0;//getTime() - gSessionData->mMonotonicStarted;
 
        if (!readProcComms(currTime, mBuffer, &printb, &b1, &b2)) {
-               logg->logError(__FILE__, __LINE__, "readProcComms failed");
+               logg->logError("readProcComms failed");
                handleException();
        }
 
@@ -124,33 +125,33 @@ void DriverSource::run() {
 
        // Set the maximum backtrace depth
        if (writeReadDriver("/dev/gator/backtrace_depth", &gSessionData->mBacktraceDepth)) {
-               logg->logError(__FILE__, __LINE__, "Unable to set the driver backtrace depth");
+               logg->logError("Unable to set the driver backtrace depth");
                handleException();
        }
 
        // open the buffer which calls userspace_buffer_open() in the driver
        mBufferFD = open("/dev/gator/buffer", O_RDONLY | O_CLOEXEC);
        if (mBufferFD < 0) {
-               logg->logError(__FILE__, __LINE__, "The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure.");
+               logg->logError("The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure.");
                handleException();
        }
 
        // set the tick rate of the profiling timer
        if (writeReadDriver("/dev/gator/tick", &gSessionData->mSampleRate) != 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to set the driver tick");
+               logg->logError("Unable to set the driver tick");
                handleException();
        }
 
        // notify the kernel of the response type
        int response_type = gSessionData->mLocalCapture ? 0 : RESPONSE_APC_DATA;
        if (writeDriver("/dev/gator/response_type", response_type)) {
-               logg->logError(__FILE__, __LINE__, "Unable to write the response type");
+               logg->logError("Unable to write the response type");
                handleException();
        }
 
        // Set the live rate
        if (writeReadDriver("/dev/gator/live_rate", &gSessionData->mLiveRate)) {
-               logg->logError(__FILE__, __LINE__, "Unable to set the driver live rate");
+               logg->logError("Unable to set the driver live rate");
                handleException();
        }
 
@@ -158,7 +159,7 @@ void DriverSource::run() {
 
        // This command makes the driver start profiling by calling gator_op_start() in the driver
        if (writeDriver("/dev/gator/enable", "1") != 0) {
-               logg->logError(__FILE__, __LINE__, "The gator driver did not start properly. Please view the linux console or dmesg log for more information on the failure.");
+               logg->logError("The gator driver did not start properly. Please view the linux console or dmesg log for more information on the failure.");
                handleException();
        }
 
@@ -168,7 +169,7 @@ void DriverSource::run() {
 
        pthread_t bootstrapThreadID;
        if (pthread_create(&bootstrapThreadID, NULL, bootstrapThreadStatic, this) != 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to start the gator_bootstrap thread");
+               logg->logError("Unable to start the gator_bootstrap thread");
                handleException();
        }
 
@@ -190,7 +191,7 @@ void DriverSource::run() {
                // In one shot mode, stop collection once all the buffers are filled
                if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
                        if (bytesCollected == -1 || mFifo->willFill(bytesCollected)) {
-                               logg->logMessage("One shot");
+                               logg->logMessage("One shot (gator.ko)");
                                child->endSession();
                        }
                }
index ec27b0815bbfe52dfbce9dcd52cf5a3829401a1b..32d983d6d0362d43a176e9d50559c2511a16b2b4 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index df20713ad63cac928b96b6e9bbd9faf09951a575..690cbcb942933e495f6701cd4b29a1e7cce95789 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -42,7 +42,7 @@ bool DynBuf::read(const char *const path) {
 
        const int fd = open(path, O_RDONLY | O_CLOEXEC);
        if (fd < 0) {
-               logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("open failed");
                return false;
        }
 
@@ -52,14 +52,14 @@ bool DynBuf::read(const char *const path) {
                const size_t minCapacity = length + MIN_BUFFER_FREE + 1;
                if (capacity < minCapacity) {
                        if (resize(minCapacity) != 0) {
-                               logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
+                               logg->logMessage("DynBuf::resize failed");
                                goto fail;
                        }
                }
 
                const ssize_t bytes = ::read(fd, buf + length, capacity - length - 1);
                if (bytes < 0) {
-                       logg->logMessage("%s(%s:%i): read failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("read failed");
                        goto fail;
                } else if (bytes == 0) {
                        break;
@@ -105,7 +105,7 @@ bool DynBuf::printf(const char *format, ...) {
 
        if (capacity <= 0) {
                if (resize(2 * MIN_BUFFER_FREE) != 0) {
-                       logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("DynBuf::resize failed");
                        return false;
                }
        }
@@ -114,13 +114,13 @@ bool DynBuf::printf(const char *format, ...) {
        int bytes = vsnprintf(buf, capacity, format, ap);
        va_end(ap);
        if (bytes < 0) {
-               logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("fsnprintf failed");
                return false;
        }
 
        if (static_cast<size_t>(bytes) > capacity) {
                if (resize(bytes + 1) != 0) {
-                       logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("DynBuf::resize failed");
                        return false;
                }
 
@@ -128,7 +128,7 @@ bool DynBuf::printf(const char *format, ...) {
                bytes = vsnprintf(buf, capacity, format, ap);
                va_end(ap);
                if (bytes < 0) {
-                       logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("fsnprintf failed");
                        return false;
                }
        }
index 2f4554ab2e491f4333e34d4fdda6a8fe8ed88dd6..da83cd65ca3eb9ff9a9795574592a6b00d4a73d4 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index d905bbabe98853cb760dfc3ad0c951e3c449faab..cec08d5a6fff9cec0d464b0b002f188afcc504dc 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
 #include "OlyUtility.h"
 #include "SessionData.h"
 
+class XMLList {
+public:
+       XMLList(XMLList *const prev, mxml_node_t *const node) : mPrev(prev), mNode(node) {}
+
+       XMLList *getPrev() { return mPrev; }
+       mxml_node_t *getNode() const { return mNode; }
+       void setNode(mxml_node_t *const node) { mNode = node; }
+
+       static void free(XMLList *list) {
+               while (list != NULL) {
+                       XMLList *prev = list->getPrev();
+                       delete list;
+                       list = prev;
+               }
+       }
+
+private:
+       XMLList *const mPrev;
+       mxml_node_t *mNode;
+
+       // Intentionally unimplemented
+       XMLList(const XMLList &);
+       XMLList &operator=(const XMLList &);
+};
+
 mxml_node_t *EventsXML::getTree() {
 #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len
        char path[PATH_MAX];
-       mxml_node_t *xml;
+       mxml_node_t *xml = NULL;
        FILE *fl;
 
        // Avoid unused variable warning
@@ -25,19 +50,147 @@ mxml_node_t *EventsXML::getTree() {
        // Load the provided or default events xml
        if (gSessionData->mEventsXMLPath) {
                strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX);
-       } else {
-               util->getApplicationFullPath(path, PATH_MAX);
-               strncat(path, "events.xml", PATH_MAX - strlen(path) - 1);
+               fl = fopen(path, "r");
+               if (fl) {
+                       xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK);
+                       fclose(fl);
+               }
        }
-       fl = fopen(path, "r");
-       if (fl) {
-               xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK);
-               fclose(fl);
-       } else {
+       if (xml == NULL) {
                logg->logMessage("Unable to locate events.xml, using default");
                xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK);
        }
 
+       // Append additional events XML
+       if (gSessionData->mEventsXMLAppend) {
+               fl = fopen(gSessionData->mEventsXMLAppend, "r");
+               if (fl == NULL) {
+                       logg->logError("Unable to open additional events XML %s", gSessionData->mEventsXMLAppend);
+                       handleException();
+               }
+               mxml_node_t *append = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK);
+               fclose(fl);
+
+               mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND);
+               if (!events) {
+                       logg->logError("Unable to find <events> node in the events.xml, please ensure the first two lines of events XML starts with:\n"
+                                      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                                      "<events>");
+                       handleException();
+               }
+
+               XMLList *categoryList = NULL;
+               XMLList *eventList = NULL;
+               {
+                       // Make list of all categories in xml
+                       mxml_node_t *node = xml;
+                       while (true) {
+                               node = mxmlFindElement(node, xml, "category", NULL, NULL, MXML_DESCEND);
+                               if (node == NULL) {
+                                       break;
+                               }
+                               categoryList = new XMLList(categoryList, node);
+                       }
+
+                       // Make list of all events in xml
+                       node = xml;
+                       while (true) {
+                               node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
+                               if (node == NULL) {
+                                       break;
+                               }
+                               eventList = new XMLList(eventList, node);
+                       }
+               }
+
+               // Handle events
+               for (mxml_node_t *node = mxmlFindElement(append, append, "event", NULL, NULL, MXML_DESCEND),
+                      *next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND);
+                    node != NULL;
+                    node = next, next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND)) {
+                       const char *const category = mxmlElementGetAttr(mxmlGetParent(node), "name");
+                       const char *const title = mxmlElementGetAttr(node, "title");
+                       const char *const name = mxmlElementGetAttr(node, "name");
+                       if (category == NULL || title == NULL || name == NULL) {
+                               logg->logError("Not all event XML nodes have the required title and name and parent name attributes");
+                               handleException();
+                       }
+
+                       // Replace any duplicate events
+                       for (XMLList *event = eventList; event != NULL; event = event->getPrev()) {
+                               const char *const category2 = mxmlElementGetAttr(mxmlGetParent(event->getNode()), "name");
+                               const char *const title2 = mxmlElementGetAttr(event->getNode(), "title");
+                               const char *const name2 = mxmlElementGetAttr(event->getNode(), "name");
+                               if (category2 == NULL || title2 == NULL || name2 == NULL) {
+                                       logg->logError("Not all event XML nodes have the required title and name and parent name attributes");
+                                       handleException();
+                               }
+
+                               if (strcmp(category, category2) == 0 && strcmp(title, title2) == 0 && strcmp(name, name2) == 0) {
+                                       logg->logMessage("Replacing counter %s %s: %s", category, title, name);
+                                       mxml_node_t *parent = mxmlGetParent(event->getNode());
+                                       mxmlDelete(event->getNode());
+                                       mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
+                                       event->setNode(node);
+                                       break;
+                               }
+                       }
+               }
+
+               // Handle categories
+               for (mxml_node_t *node = strcmp(mxmlGetElement(append), "category") == 0 ? append : mxmlFindElement(append, append, "category", NULL, NULL, MXML_DESCEND),
+                      *next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND);
+                    node != NULL;
+                    node = next, next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND)) {
+                       // After replacing duplicate events, a category may be empty
+                       if (mxmlGetFirstChild(node) == NULL) {
+                               continue;
+                       }
+
+                       const char *const name = mxmlElementGetAttr(node, "name");
+                       if (name == NULL) {
+                               logg->logError("Not all event XML categories have the required name attribute");
+                               handleException();
+                       }
+
+                       // Merge identically named categories
+                       bool merged = false;
+                       for (XMLList *category = categoryList; category != NULL; category = category->getPrev()) {
+                               const char *const name2 = mxmlElementGetAttr(category->getNode(), "name");
+                               if (name2 == NULL) {
+                                       logg->logError("Not all event XML categories have the required name attribute");
+                                       handleException();
+                               }
+
+                               if (strcmp(name, name2) == 0) {
+                                       logg->logMessage("Merging category %s", name);
+                                       while (true) {
+                                               mxml_node_t *child = mxmlGetFirstChild(node);
+                                               if (child == NULL) {
+                                                       break;
+                                               }
+                                               mxmlAdd(category->getNode(), MXML_ADD_AFTER, mxmlGetLastChild(category->getNode()), child);
+                                       }
+                                       merged = true;
+                                       break;
+                               }
+                       }
+
+                       if (merged) {
+                               continue;
+                       }
+
+                       // Add new categories
+                       logg->logMessage("Appending category %s", name);
+                       mxmlAdd(events, MXML_ADD_AFTER, mxmlGetLastChild(events), node);
+               }
+
+               XMLList::free(eventList);
+               XMLList::free(categoryList);
+
+               mxmlDelete(append);
+       }
+
        return xml;
 }
 
@@ -47,7 +200,9 @@ char *EventsXML::getXML() {
        // Add dynamic events from the drivers
        mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND);
        if (!events) {
-               logg->logError(__FILE__, __LINE__, "Unable to find <events> node in the events.xml");
+               logg->logError("Unable to find <events> node in the events.xml, please ensure the first two lines of events XML are:\n"
+                              "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                              "<events>");
                handleException();
        }
        for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
@@ -68,7 +223,7 @@ void EventsXML::write(const char *path) {
 
        char *buf = getXML();
        if (util->writeToDisk(file, buf) < 0) {
-               logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
+               logg->logError("Error writing %s\nPlease verify the path.", file);
                handleException();
        }
 
index ff7a02fd3c78b56dd702cdffaa30da86bcac2e4a..2b38fa4364e00a83b26cce6f5f781f47381534e2 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
 
 class EventsXML {
 public:
+       EventsXML() {}
+
        mxml_node_t *getTree();
        char *getXML();
        void write(const char* path);
+
+private:
+       // Intentionally unimplemented
+       EventsXML(const EventsXML &);
+       EventsXML &operator=(const EventsXML &);
 };
 
 #endif // EVENTS_XML
index 8f5e6b684c538b192c03ab40529836d61a4d2157..8d71b6de3d5ecee098088684feadcba7da63fa66 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
 #include <sys/prctl.h>
 #include <unistd.h>
 
+#include "Child.h"
 #include "Logging.h"
 #include "OlySocket.h"
 #include "SessionData.h"
 
+extern Child *child;
+
+static const char STREAMLINE_ANNOTATE[] = "\0streamline-annotate";
 static const char MALI_VIDEO[] = "\0mali-video";
 static const char MALI_VIDEO_STARTUP[] = "\0mali-video-startup";
 static const char MALI_VIDEO_V1[] = "MALI_VIDEO 1\n";
@@ -40,7 +44,7 @@ static bool setNonblock(const int fd) {
        return true;
 }
 
-ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mMaliStartupUds(MALI_GRAPHICS_STARTUP, sizeof(MALI_GRAPHICS_STARTUP)), mAnnotate(8083), mInterruptFd(-1), mMaliUds(-1), mMveUds(-1) {
+ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mMaliStartupUds(MALI_GRAPHICS_STARTUP, sizeof(MALI_GRAPHICS_STARTUP)), mAnnotate(8083), mAnnotateUds(STREAMLINE_ANNOTATE, sizeof(STREAMLINE_ANNOTATE), true), mInterruptFd(-1), mMaliUds(-1), mMveUds(-1) {
        sem_init(&mBufferSem, 0, 0);
 }
 
@@ -49,18 +53,22 @@ ExternalSource::~ExternalSource() {
 
 void ExternalSource::waitFor(const int bytes) {
        while (mBuffer.bytesAvailable() <= bytes) {
+               if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
+                       logg->logMessage("One shot (external)");
+                       child->endSession();
+               }
                sem_wait(&mBufferSem);
        }
 }
 
 void ExternalSource::configureConnection(const int fd, const char *const handshake, size_t size) {
        if (!setNonblock(fd)) {
-               logg->logError(__FILE__, __LINE__, "Unable to set nonblock on fh");
+               logg->logError("Unable to set nonblock on fh");
                handleException();
        }
 
        if (!mMonitor.add(fd)) {
-               logg->logError(__FILE__, __LINE__, "Unable to add fh to monitor");
+               logg->logError("Unable to add fh to monitor");
                handleException();
        }
 
@@ -68,7 +76,7 @@ void ExternalSource::configureConnection(const int fd, const char *const handsha
        waitFor(Buffer::MAXSIZE_PACK32 + size - 1);
        mBuffer.packInt(fd);
        mBuffer.writeBytes(handshake, size - 1);
-       mBuffer.commit(1);
+       mBuffer.commit(1, true);
 }
 
 bool ExternalSource::connectMali() {
@@ -106,6 +114,7 @@ bool ExternalSource::prepare() {
                        !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd()) ||
                        !setNonblock(mMaliStartupUds.getFd()) || !mMonitor.add(mMaliStartupUds.getFd()) ||
                        !setNonblock(mAnnotate.getFd()) || !mMonitor.add(mAnnotate.getFd()) ||
+                       !setNonblock(mAnnotateUds.getFd()) || !mMonitor.add(mAnnotateUds.getFd()) ||
                        false) {
                return false;
        }
@@ -122,18 +131,21 @@ void ExternalSource::run() {
        prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0);
 
        if (pipe_cloexec(pipefd) != 0) {
-               logg->logError(__FILE__, __LINE__, "pipe failed");
+               logg->logError("pipe failed");
                handleException();
        }
        mInterruptFd = pipefd[1];
 
        if (!mMonitor.add(pipefd[0])) {
-               logg->logError(__FILE__, __LINE__, "Monitor::add failed");
+               logg->logError("Monitor::add failed");
                handleException();
        }
 
        // Notify annotate clients to retry connecting to gatord
-       gSessionData->annotateListener.signal();
+       uint64_t val = 1;
+       if (::write(gSessionData->mAnnotateStart, &val, sizeof(val)) != sizeof(val)) {
+               logg->logMessage("Writing to annotate pipe failed");
+       }
 
        while (gSessionData->mSessionIsActive) {
                struct epoll_event events[16];
@@ -141,11 +153,11 @@ void ExternalSource::run() {
                while (sem_trywait(&mBufferSem) == 0);
                int ready = mMonitor.wait(events, ARRAY_LENGTH(events), -1);
                if (ready < 0) {
-                       logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
+                       logg->logError("Monitor::wait failed");
                        handleException();
                }
 
-               const uint64_t currTime = getTime();
+               const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted;
 
                for (int i = 0; i < ready; ++i) {
                        const int fd = events[i].data.fd;
@@ -155,7 +167,7 @@ void ExternalSource::run() {
                                // Don't read from this connection, establish a new connection to Mali-V500
                                close(client);
                                if (!connectMve()) {
-                                       logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection");
+                                       logg->logError("Unable to configure incoming Mali video connection");
                                        handleException();
                                }
                        } else if (fd == mMaliStartupUds.getFd()) {
@@ -164,13 +176,19 @@ void ExternalSource::run() {
                                // Don't read from this connection, establish a new connection to Mali Graphics
                                close(client);
                                if (!connectMali()) {
-                                       logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali graphics connection");
+                                       logg->logError("Unable to configure incoming Mali graphics connection");
                                        handleException();
                                }
                        } else if (fd == mAnnotate.getFd()) {
                                int client = mAnnotate.acceptConnection();
                                if (!setNonblock(client) || !mMonitor.add(client)) {
-                                       logg->logError(__FILE__, __LINE__, "Unable to set socket options on incoming annotation connection");
+                                       logg->logError("Unable to set socket options on incoming annotation connection");
+                                       handleException();
+                               }
+                       } else if (fd == mAnnotateUds.getFd()) {
+                               int client = mAnnotateUds.acceptConnection();
+                               if (!setNonblock(client) || !mMonitor.add(client)) {
+                                       logg->logError("Unable to set socket options on incoming annotation connection");
                                        handleException();
                                }
                        } else if (fd == pipefd[0]) {
@@ -190,28 +208,29 @@ void ExternalSource::run() {
                                        if (bytes < 0) {
                                                if (errno == EAGAIN) {
                                                        // Nothing left to read
-                                                       mBuffer.commit(currTime);
+                                                       mBuffer.commit(currTime, true);
                                                        break;
                                                }
                                                // Something else failed, close the socket
-                                               mBuffer.commit(currTime);
+                                               mBuffer.commit(currTime, true);
                                                mBuffer.packInt(-1);
                                                mBuffer.packInt(fd);
-                                               mBuffer.commit(currTime);
+                                               // Here and other commits, always force-flush the buffer as this frame don't work like others
+                                               mBuffer.commit(currTime, true);
                                                close(fd);
                                                break;
                                        } else if (bytes == 0) {
                                                // The other side is closed
-                                               mBuffer.commit(currTime);
+                                               mBuffer.commit(currTime, true);
                                                mBuffer.packInt(-1);
                                                mBuffer.packInt(fd);
-                                               mBuffer.commit(currTime);
+                                               mBuffer.commit(currTime, true);
                                                close(fd);
                                                break;
                                        }
 
                                        mBuffer.advanceWrite(bytes);
-                                       mBuffer.commit(currTime);
+                                       mBuffer.commit(currTime, true);
 
                                        // Short reads also mean nothing is left to read
                                        if (bytes < contiguous) {
@@ -238,7 +257,7 @@ void ExternalSource::interrupt() {
                int8_t c = 0;
                // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread
                if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) {
-                       logg->logError(__FILE__, __LINE__, "write failed");
+                       logg->logError("write failed");
                        handleException();
                }
        }
index 919e75e8a41af34d8935d8b58e3d6395602f87b6..25ae7cd4c4ab32f9a37168a9cf4ebe0dca2beff2 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -41,6 +41,7 @@ private:
        OlyServerSocket mMveStartupUds;
        OlyServerSocket mMaliStartupUds;
        OlyServerSocket mAnnotate;
+       OlyServerSocket mAnnotateUds;
        int mInterruptFd;
        int mMaliUds;
        int mMveUds;
index dd8eb804dc99863f67aa42825c0f34b7ff317aca..afac9dfb676147fc492c7c96ddd25d34d0576a1c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -42,7 +42,7 @@ FSCounter::FSCounter(DriverCounter *next, char *name, char *path, const char *re
                if (result != 0) {
                        char buf[128];
                        regerror(result, &mReg, buf, sizeof(buf));
-                       logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
+                       logg->logError("Invalid regex '%s': %s", regex, buf);
                        handleException();
                }
        }
@@ -79,21 +79,19 @@ int64_t FSCounter::read() {
                regmatch_t match[2];
                int result = regexec(&mReg, buf, 2, match, 0);
                if (result != 0) {
-                       regerror(result, &mReg, buf, sizeof(buf));
-                       logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, buf);
-                       handleException();
+                       // No match
+                       return 0;
                }
 
                if (match[1].rm_so < 0) {
-                       logg->logError(__FILE__, __LINE__, "Parsing %s failed", mPath);
-                       handleException();
-               }
-
-               errno = 0;
-               value = strtoll(buf + match[1].rm_so, NULL, 0);
-               if (errno != 0) {
-                       logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, strerror(errno));
-                       handleException();
+                       value = 1;
+               } else {
+                       errno = 0;
+                       value = strtoll(buf + match[1].rm_so, NULL, 0);
+                       if (errno != 0) {
+                               logg->logError("Parsing %s failed: %s", mPath, strerror(errno));
+                               handleException();
+                       }
                }
        } else {
                if (DriverSource::readInt64Driver(mPath, &value) != 0) {
@@ -103,7 +101,7 @@ int64_t FSCounter::read() {
        return value;
 
  fail:
-       logg->logError(__FILE__, __LINE__, "Unable to read %s", mPath);
+       logg->logError("Unable to read %s", mPath);
        handleException();
 }
 
@@ -126,7 +124,7 @@ void FSDriver::readEvents(mxml_node_t *const xml) {
                }
 
                if (counter[0] == '/') {
-                       logg->logError(__FILE__, __LINE__, "Old style filesystem counter (%s) detected, please create a new unique counter value and move the filename into the path attribute, see events-Filesystem.xml for examples", counter);
+                       logg->logError("Old style filesystem counter (%s) detected, please create a new unique counter value and move the filename into the path attribute, see events-Filesystem.xml for examples", counter);
                        handleException();
                }
 
@@ -136,7 +134,7 @@ void FSDriver::readEvents(mxml_node_t *const xml) {
 
                const char *path = mxmlElementGetAttr(node, "path");
                if (path == NULL) {
-                       logg->logError(__FILE__, __LINE__, "The filesystem counter %s is missing the required path attribute", counter);
+                       logg->logError("The filesystem counter %s is missing the required path attribute", counter);
                        handleException();
                }
                const char *regex = mxmlElementGetAttr(node, "regex");
index a7dc8b4df9dde673f92af1d2829f045e2cc9402e..63a4e90a2b4619a4d75c1510464eefe5eb587a8b 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
index 41275fd287b8c7a803ced309fd0d5f5e30d49848..8d3b9ff8d385889c888588a0e1c68a8d3c2231cf 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -24,12 +24,12 @@ Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) {
   mEnd = false;
 
   if (mBuffer == NULL) {
-    logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize);
+    logg->logError("failed to allocate %d bytes", bufferSize + singleBufferSize);
     handleException();
   }
 
   if (sem_init(&mWaitForSpaceSem, 0, 0)) {
-    logg->logError(__FILE__, __LINE__, "sem_init() failed");
+    logg->logError("sem_init() failed");
     handleException();
   }
 }
index 21c8d8580391230eb992e8032b92c6d84a6d627a..01fa11b2f2c479abfb65e3bb390b5f7a869ceda0 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index b156f1c0b8b46f1341477071f7b47106f669fbff..98bd0a5d9eece006ddf4c9c3f2deea86d1db808c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -9,56 +9,80 @@
 #include "FtraceDriver.h"
 
 #include <regex.h>
+#include <unistd.h>
 
+#include "DriverSource.h"
 #include "Logging.h"
+#include "Setup.h"
 
 class FtraceCounter : public DriverCounter {
 public:
-       FtraceCounter(DriverCounter *next, char *name, const char *regex);
+       FtraceCounter(DriverCounter *next, char *name, const char *regex, const char *enable);
        ~FtraceCounter();
 
+       void prepare();
        int read(const char *const line, int64_t *values);
+       void stop();
 
 private:
-       regex_t reg;
+       regex_t mReg;
+       char *const mEnable;
+       int mWasEnabled;
 
        // Intentionally unimplemented
        FtraceCounter(const FtraceCounter &);
        FtraceCounter &operator=(const FtraceCounter &);
 };
 
-FtraceCounter::FtraceCounter(DriverCounter *next, char *name, const char *regex) : DriverCounter(next, name) {
-       int result = regcomp(&reg, regex, REG_EXTENDED);
+FtraceCounter::FtraceCounter(DriverCounter *next, char *name, const char *regex, const char *enable) : DriverCounter(next, name), mEnable(enable == NULL ? NULL : strdup(enable)) {
+       int result = regcomp(&mReg, regex, REG_EXTENDED);
        if (result != 0) {
                char buf[128];
-               regerror(result, &reg, buf, sizeof(buf));
-               logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
+               regerror(result, &mReg, buf, sizeof(buf));
+               logg->logError("Invalid regex '%s': %s", regex, buf);
                handleException();
        }
 }
 
 FtraceCounter::~FtraceCounter() {
-       regfree(&reg);
+       regfree(&mReg);
+       if (mEnable != NULL) {
+               free(mEnable);
+       }
+}
+
+void FtraceCounter::prepare() {
+       if (mEnable == NULL) {
+               return;
+       }
+
+       char buf[1<<10];
+       snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%s/enable", mEnable);
+       if ((DriverSource::readIntDriver(buf, &mWasEnabled) != 0) ||
+                       (DriverSource::writeDriver(buf, 1) != 0)) {
+               logg->logError("Unable to read or write to %s", buf);
+               handleException();
+       }
 }
 
 int FtraceCounter::read(const char *const line, int64_t *values) {
        regmatch_t match[2];
-       int result = regexec(&reg, line, 2, match, 0);
+       int result = regexec(&mReg, line, 2, match, 0);
        if (result != 0) {
                // No match
                return 0;
        }
 
+       int64_t value;
        if (match[1].rm_so < 0) {
-               logg->logError(__FILE__, __LINE__, "Parsing %s failed", getName());
-               handleException();
-       }
-
-       errno = 0;
-       int64_t value = strtoll(line + match[1].rm_so, NULL, 0);
-       if (errno != 0) {
-               logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", getName(), strerror(errno));
-               handleException();
+               value = 1;
+       } else {
+               errno = 0;
+               value = strtoll(line + match[1].rm_so, NULL, 0);
+               if (errno != 0) {
+                       logg->logError("Parsing %s failed: %s", getName(), strerror(errno));
+                       handleException();
+               }
        }
 
        values[0] = getKey();
@@ -67,6 +91,16 @@ int FtraceCounter::read(const char *const line, int64_t *values) {
        return 1;
 }
 
+void FtraceCounter::stop() {
+       if (mEnable == NULL) {
+               return;
+       }
+
+       char buf[1<<10];
+       snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%s/enable", mEnable);
+       DriverSource::writeDriver(buf, mWasEnabled);
+}
+
 FtraceDriver::FtraceDriver() : mValues(NULL) {
 }
 
@@ -75,6 +109,19 @@ FtraceDriver::~FtraceDriver() {
 }
 
 void FtraceDriver::readEvents(mxml_node_t *const xml) {
+       // Check the kernel version
+       int release[3];
+       if (!getLinuxVersion(release)) {
+               logg->logError("getLinuxVersion failed");
+               handleException();
+       }
+
+       // The perf clock was added in 3.10
+       if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 10, 0)) {
+               logg->logMessage("Unsupported kernel version, to use ftrace please upgrade to Linux 3.10 or later");
+               return;
+       }
+
        mxml_node_t *node = xml;
        int count = 0;
        while (true) {
@@ -93,16 +140,37 @@ void FtraceDriver::readEvents(mxml_node_t *const xml) {
 
                const char *regex = mxmlElementGetAttr(node, "regex");
                if (regex == NULL) {
-                       logg->logError(__FILE__, __LINE__, "The regex counter %s is missing the required regex attribute", counter);
+                       logg->logError("The regex counter %s is missing the required regex attribute", counter);
                        handleException();
                }
-               setCounters(new FtraceCounter(getCounters(), strdup(counter), regex));
-               ++count;
+               bool addCounter = true;
+               const char *enable = mxmlElementGetAttr(node, "enable");
+               if (enable != NULL) {
+                       char buf[1<<10];
+                       snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%s/enable", enable);
+                       if (access(buf, W_OK) != 0) {
+                               logg->logMessage("Disabling counter %s, %s not found", counter, buf);
+                               addCounter = false;
+                       }
+               }
+               if (addCounter) {
+                       setCounters(new FtraceCounter(getCounters(), strdup(counter), regex, enable));
+                       ++count;
+               }
        }
 
        mValues = new int64_t[2*count];
 }
 
+void FtraceDriver::prepare() {
+       for (FtraceCounter *counter = static_cast<FtraceCounter *>(getCounters()); counter != NULL; counter = static_cast<FtraceCounter *>(counter->getNext())) {
+               if (!counter->isEnabled()) {
+                       continue;
+               }
+               counter->prepare();
+       }
+}
+
 int FtraceDriver::read(const char *line, int64_t **buf) {
        int count = 0;
 
@@ -116,3 +184,12 @@ int FtraceDriver::read(const char *line, int64_t **buf) {
        *buf = mValues;
        return count;
 }
+
+void FtraceDriver::stop() {
+       for (FtraceCounter *counter = static_cast<FtraceCounter *>(getCounters()); counter != NULL; counter = static_cast<FtraceCounter *>(counter->getNext())) {
+               if (!counter->isEnabled()) {
+                       continue;
+               }
+               counter->stop();
+       }
+}
index 5f958bec672cea5f67a76bfc0acbd0244ce8b6e8..b79dc9149d6aec1f88806bba369325af4be60efc 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -18,7 +18,9 @@ public:
 
        void readEvents(mxml_node_t *const xml);
 
+       void prepare();
        int read(const char *line, int64_t **buf);
+       void stop();
 
 private:
        int64_t *mValues;
index 521633357417142831635c07eaec1a61512a84e0..14a48b3b870cf54d906ff1ea9029cf406d708bac 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
 #include <sys/syscall.h>
 #include <unistd.h>
 
+#include "Child.h"
 #include "DriverSource.h"
 #include "Logging.h"
 #include "SessionData.h"
 
+extern Child *child;
+
 static void handler(int signum)
 {
        (void)signum;
@@ -35,18 +38,20 @@ bool FtraceSource::prepare() {
                act.sa_handler = handler;
                act.sa_flags = (int)SA_RESETHAND;
                if (sigaction(SIGUSR1, &act, NULL) != 0) {
-                       logg->logError(__FILE__, __LINE__, "sigaction failed: %s\n", strerror(errno));
+                       logg->logError("sigaction failed: %s\n", strerror(errno));
                        handleException();
                }
        }
 
+       gSessionData->ftraceDriver.prepare();
+
        if (DriverSource::readIntDriver("/sys/kernel/debug/tracing/tracing_on", &mTracingOn)) {
-               logg->logError(__FILE__, __LINE__, "Unable to read if ftrace is enabled");
+               logg->logError("Unable to read if ftrace is enabled");
                handleException();
        }
 
        if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "0") != 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to turn ftrace off before truncating the buffer");
+               logg->logError("Unable to turn ftrace off before truncating the buffer");
                handleException();
        }
 
@@ -54,20 +59,20 @@ bool FtraceSource::prepare() {
                int fd;
                fd = open("/sys/kernel/debug/tracing/trace", O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
                if (fd < 0) {
-                       logg->logError(__FILE__, __LINE__, "Unable truncate ftrace buffer: %s", strerror(errno));
+                       logg->logError("Unable truncate ftrace buffer: %s", strerror(errno));
                        handleException();
                }
                close(fd);
        }
 
        if (DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "perf") != 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later");
+               logg->logError("Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later");
                handleException();
        }
 
        mFtraceFh = fopen_cloexec("/sys/kernel/debug/tracing/trace_pipe", "rb");
        if (mFtraceFh == NULL) {
-               logg->logError(__FILE__, __LINE__, "Unable to open trace_pipe");
+               logg->logError("Unable to open trace_pipe");
                handleException();
        }
 
@@ -79,10 +84,25 @@ void FtraceSource::run() {
        mTid = syscall(__NR_gettid);
 
        if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "1") != 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to turn ftrace on");
+               logg->logError("Unable to turn ftrace on");
                handleException();
        }
 
+       // Wait until monotonicStarted is set before sending data
+       int64_t monotonicStarted = 0;
+       while (monotonicStarted <= 0 && gSessionData->mSessionIsActive) {
+               usleep(10);
+
+               if (gSessionData->perf.isSetup()) {
+                       monotonicStarted = gSessionData->mMonotonicStarted;
+               } else {
+                       if (DriverSource::readInt64Driver("/dev/gator/started", &monotonicStarted) == -1) {
+                               logg->logError("Error reading gator driver start time");
+                               handleException();
+                       }
+               }
+       }
+
        while (gSessionData->mSessionIsActive) {
                char buf[1<<12];
 
@@ -91,22 +111,26 @@ void FtraceSource::run() {
                                // Interrupted by interrupt - likely user request to terminate
                                break;
                        }
-                       logg->logError(__FILE__, __LINE__, "Unable read trace data: %s", strerror(errno));
+                       logg->logError("Unable read trace data: %s", strerror(errno));
                        handleException();
                }
 
-               const uint64_t currTime = getTime();
+               const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted;
 
                char *const colon = strstr(buf, ": ");
                if (colon == NULL) {
-                       logg->logError(__FILE__, __LINE__, "Unable find colon: %s", buf);
+                       if (strstr(buf, " [LOST ") != NULL) {
+                               logg->logError("Ftrace events lost, aborting the capture. It is recommended to discard this report and collect a new capture. If this error occurs often, please reduce the number of ftrace counters selected or the amount of ftrace events generated.");
+                       } else {
+                               logg->logError("Unable to find colon: %s", buf);
+                       }
                        handleException();
                }
                *colon = '\0';
 
                char *const space = strrchr(buf, ' ');
                if (space == NULL) {
-                       logg->logError(__FILE__, __LINE__, "Unable find space: %s", buf);
+                       logg->logError("Unable to find space: %s", buf);
                        handleException();
                }
                *colon = ':';
@@ -117,7 +141,7 @@ void FtraceSource::run() {
                        errno = 0;
                        const long long time = strtod(space, NULL) * 1000000000;
                        if (errno != 0) {
-                               logg->logError(__FILE__, __LINE__, "Unable to parse time: %s", strerror(errno));
+                               logg->logError("Unable to parse time: %s", strerror(errno));
                                handleException();
                        }
                        mBuffer.event64(-1, time);
@@ -127,6 +151,11 @@ void FtraceSource::run() {
                        }
 
                        mBuffer.check(currTime);
+
+                       if (gSessionData->mOneShot && gSessionData->mSessionIsActive && (mBuffer.bytesAvailable() <= 0)) {
+                               logg->logMessage("One shot (ftrace)");
+                               child->endSession();
+                       }
                }
 
        }
@@ -136,6 +165,7 @@ void FtraceSource::run() {
        DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", mTracingOn);
        fclose(mFtraceFh);
        DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "local");
+       gSessionData->ftraceDriver.stop();
 }
 
 void FtraceSource::interrupt() {
index 2391b881494e2637912218a9753a19b46dbf9dc3..bc068d2666544d48cb35f6b0099cee88cacb5b92 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 9d161ae5ac560c2469f55cd47d883ee714ad6663..d8353b006e63d1196d0bddf31e3b422be945ea03 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -23,7 +23,7 @@ static sensors_subfeature_type getInput(const sensors_feature_type type) {
        case SENSORS_FEATURE_CURR: return SENSORS_SUBFEATURE_CURR_INPUT;
        case SENSORS_FEATURE_HUMIDITY: return SENSORS_SUBFEATURE_HUMIDITY_INPUT;
        default:
-               logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", type);
+               logg->logError("Unsupported hwmon feature %i", type);
                handleException();
        }
 };
@@ -33,112 +33,112 @@ public:
        HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature);
        ~HwmonCounter();
 
-       const char *getLabel() const { return label; }
-       const char *getTitle() const { return title; }
-       bool isDuplicate() const { return duplicate; }
-       const char *getDisplay() const { return display; }
-       const char *getCounterClass() const { return counter_class; }
-       const char *getUnit() const { return unit; }
-       int getModifier() const { return modifier; }
+       const char *getLabel() const { return mLabel; }
+       const char *getTitle() const { return mTitle; }
+       bool isDuplicate() const { return mDuplicate; }
+       const char *getDisplay() const { return mDisplay; }
+       const char *getCounterClass() const { return mCounterClass; }
+       const char *getUnit() const { return mUnit; }
+       double getMultiplier() const { return mMultiplier; }
 
        int64_t read();
 
 private:
        void init(const sensors_chip_name *chip, const sensors_feature *feature);
 
-       const sensors_chip_name *chip;
-       const sensors_feature *feature;
-       char *label;
-       const char *title;
-       const char *display;
-       const char *counter_class;
-       const char *unit;
-       double previous_value;
-       int modifier;
-       int monotonic: 1,
-               duplicate : 1;
+       const sensors_chip_name *mChip;
+       const sensors_feature *mFeature;
+       char *mLabel;
+       const char *mTitle;
+       const char *mDisplay;
+       const char *mCounterClass;
+       const char *mUnit;
+       double mPreviousValue;
+       double mMultiplier;
+       int mMonotonic: 1,
+               mDuplicate : 1;
 
        // Intentionally unimplemented
        HwmonCounter(const HwmonCounter &);
        HwmonCounter &operator=(const HwmonCounter &);
 };
 
-HwmonCounter::HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature) : DriverCounter(next, name), chip(chip), feature(feature), duplicate(false) {
-       label = sensors_get_label(chip, feature);
+HwmonCounter::HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *const chip, const sensors_feature *feature) : DriverCounter(next, name), mChip(chip), mFeature(feature), mDuplicate(false) {
+       mLabel = sensors_get_label(mChip, mFeature);
 
-       switch (feature->type) {
+       switch (mFeature->type) {
        case SENSORS_FEATURE_IN:
-               title = "Voltage";
-               display = "maximum";
-               counter_class = "absolute";
-               unit = "V";
-               modifier = 1000;
-               monotonic = false;
+               mTitle = "Voltage";
+               mDisplay = "maximum";
+               mCounterClass = "absolute";
+               mUnit = "V";
+               mMultiplier = 0.001;
+               mMonotonic = false;
                break;
        case SENSORS_FEATURE_FAN:
-               title = "Fan";
-               display = "average";
-               counter_class = "absolute";
-               unit = "RPM";
-               modifier = 1;
-               monotonic = false;
+               mTitle = "Fan";
+               mDisplay = "average";
+               mCounterClass = "absolute";
+               mUnit = "RPM";
+               mMultiplier = 1.0;
+               mMonotonic = false;
                break;
        case SENSORS_FEATURE_TEMP:
-               title = "Temperature";
-               display = "maximum";
-               counter_class = "absolute";
-               unit = "°C";
-               modifier = 1000;
-               monotonic = false;
+               mTitle = "Temperature";
+               mDisplay = "maximum";
+               mCounterClass = "absolute";
+               mUnit = "°C";
+               mMultiplier = 0.001;
+               mMonotonic = false;
                break;
        case SENSORS_FEATURE_POWER:
-               title = "Power";
-               display = "maximum";
-               counter_class = "absolute";
-               unit = "W";
-               modifier = 1000000;
-               monotonic = false;
+               mTitle = "Power";
+               mDisplay = "maximum";
+               mCounterClass = "absolute";
+               mUnit = "W";
+               mMultiplier = 0.000001;
+               mMonotonic = false;
                break;
        case SENSORS_FEATURE_ENERGY:
-               title = "Energy";
-               display = "accumulate";
-               counter_class = "delta";
-               unit = "J";
-               modifier = 1000000;
-               monotonic = true;
+               mTitle = "Energy";
+               mDisplay = "accumulate";
+               mCounterClass = "delta";
+               mUnit = "J";
+               mMultiplier = 0.000001;
+               mMonotonic = true;
                break;
        case SENSORS_FEATURE_CURR:
-               title = "Current";
-               display = "maximum";
-               counter_class = "absolute";
-               unit = "A";
-               modifier = 1000;
-               monotonic = false;
+               mTitle = "Current";
+               mDisplay = "maximum";
+               mCounterClass = "absolute";
+               mUnit = "A";
+               mMultiplier = 0.001;
+               mMonotonic = false;
                break;
        case SENSORS_FEATURE_HUMIDITY:
-               title = "Humidity";
-               display = "average";
-               counter_class = "absolute";
-               unit = "%";
-               modifier = 1000;
-               monotonic = false;
+               mTitle = "Humidity";
+               mDisplay = "average";
+               mCounterClass = "absolute";
+               mUnit = "%";
+               mMultiplier = 0.001;
+               mMonotonic = false;
                break;
        default:
-               logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type);
+               logg->logError("Unsupported hwmon feature %i", mFeature->type);
                handleException();
        }
 
        for (HwmonCounter * counter = static_cast<HwmonCounter *>(next); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) {
-               if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) {
-                       duplicate = true;
-                       counter->duplicate = true;
+               if (strcmp(mLabel, counter->getLabel()) == 0 && strcmp(mTitle, counter->getTitle()) == 0) {
+                       mDuplicate = true;
+                       counter->mDuplicate = true;
                        break;
                }
        }
 }
 
 HwmonCounter::~HwmonCounter() {
-       free((void *)label);
+       free((void *)mLabel);
 }
 
 int64_t HwmonCounter::read() {
@@ -147,19 +147,19 @@ int64_t HwmonCounter::read() {
        const sensors_subfeature *subfeature;
 
        // Keep in sync with the read check in HwmonDriver::readEvents
-       subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type));
+       subfeature = sensors_get_subfeature(mChip, mFeature, getInput(mFeature->type));
        if (!subfeature) {
-               logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label);
+               logg->logError("No input value for hwmon sensor %s", mLabel);
                handleException();
        }
 
-       if (sensors_get_value(chip, subfeature->number, &value) != 0) {
-               logg->logError(__FILE__, __LINE__, "Can't get input value for hwmon sensor %s", label);
+       if (sensors_get_value(mChip, subfeature->number, &value) != 0) {
+               logg->logError("Can't get input value for hwmon sensor %s", mLabel);
                handleException();
        }
 
-       result = (monotonic ? value - previous_value : value);
-       previous_value = value;
+       result = (mMonotonic ? value - mPreviousValue : value);
+       mPreviousValue = value;
 
        return result;
 }
@@ -209,7 +209,7 @@ void HwmonDriver::readEvents(mxml_node_t *const) {
 
 void HwmonDriver::writeEvents(mxml_node_t *root) const {
        root = mxmlNewElement(root, "category");
-       mxmlElementSetAttr(root, "name", "hwmon");
+       mxmlElementSetAttr(root, "name", "Hardware Monitor");
 
        char buf[1024];
        for (HwmonCounter *counter = static_cast<HwmonCounter *>(getCounters()); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) {
@@ -224,8 +224,8 @@ void HwmonDriver::writeEvents(mxml_node_t *root) const {
                mxmlElementSetAttr(node, "display", counter->getDisplay());
                mxmlElementSetAttr(node, "class", counter->getCounterClass());
                mxmlElementSetAttr(node, "units", counter->getUnit());
-               if (counter->getModifier() != 1) {
-                       mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier());
+               if (counter->getMultiplier() != 1.0) {
+                       mxmlElementSetAttrf(node, "multiplier", "%lf", counter->getMultiplier());
                }
                if (strcmp(counter->getDisplay(), "average") == 0 || strcmp(counter->getDisplay(), "maximum") == 0) {
                        mxmlElementSetAttr(node, "average_selection", "yes");
index f28d825e3b7b69110c3793d45d6dad86ac1e1c1e..f15d557051dc110c949d6188d81ac5c90dc54020 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index fe9dc6a7e4f7027919743189dd52c5a9c1905266..e33b499d831b1dccc764b043ff8a47ea31115f89 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -83,13 +83,13 @@ void KMod::setupCounter(Counter &counter) {
        if (access(text, F_OK) == 0) {
                int count = counter.getCount();
                if (DriverSource::writeReadDriver(text, &count) && counter.getCount() > 0) {
-                       logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s:%i with a count of %d\n", counter.getType(), counter.getEvent(), counter.getCount());
+                       logg->logError("Cannot enable EBS for %s:%i with a count of %d\n", counter.getType(), counter.getEvent(), counter.getCount());
                        handleException();
                }
                counter.setCount(count);
        } else if (counter.getCount() > 0) {
                ConfigurationXML::remove();
-               logg->logError(__FILE__, __LINE__, "Event Based Sampling is only supported with kernel versions 3.0.0 and higher with CONFIG_PERF_EVENTS=y, and CONFIG_HW_PERF_EVENTS=y. The invalid configuration.xml has been removed.\n");
+               logg->logError("Event Based Sampling is only supported with kernel versions 3.0.0 and higher with CONFIG_PERF_EVENTS=y, and CONFIG_HW_PERF_EVENTS=y. The invalid configuration.xml has been removed.\n");
                handleException();
        }
 }
index 900a60e87d24d605957fc58eb4653a1ffd7840d9..7f06b4b34b5d9b1072dc6c8bb95e9f5470e3210d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index d2a4b799d7ac721e25f141054bff1d3bb86bba9e..56899871c03a090f55c1b15d2e5c51759024a05a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -27,7 +27,7 @@ LocalCapture::~LocalCapture() {}
 void LocalCapture::createAPCDirectory(char* target_path) {
        gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc");
        if ((removeDirAndAllContents(gSessionData->mAPCDir) != 0 || mkdir(gSessionData->mAPCDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
-               logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->mAPCDir);
+               logg->logError("Unable to create directory %s", gSessionData->mAPCDir);
                handleException();
        }
 }
@@ -40,7 +40,7 @@ void LocalCapture::write(char* string) {
 
        // Write the file
        if (util->writeToDisk(file, string) < 0) {
-               logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
+               logg->logError("Error writing %s\nPlease verify the path.", file);
                handleException();
        }
 
@@ -55,7 +55,7 @@ char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* e
 
        // Ensure the path is an absolute path, i.e. starts with a slash
        if (initialPath == 0 || strlen(initialPath) == 0) {
-               logg->logError(__FILE__, __LINE__, "Missing -o command line option required for a local capture.");
+               logg->logError("Missing -o command line option required for a local capture.");
                handleException();
        } else if (initialPath[0] != '/') {
                if (getcwd(path, PATH_MAX) == 0) {
index 25d281f8328b4d2b433f9ea037503baf626f4cdf..807f49d1684536017de4fc9a580200daa868242b 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 41ffa1a45151c814aa0de13971a55fc7b17e08be..8846622d950f0def1da4a45f6d6d357a6c807786 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -39,12 +39,12 @@ Logging::Logging(bool debug) {
 Logging::~Logging() {
 }
 
-void Logging::logError(const char* file, int line, const char* fmt, ...) {
+void Logging::_logError(const char *function, const char *file, int line, const char *fmt, ...) {
        va_list args;
 
        MUTEX_LOCK();
        if (mDebug) {
-               snprintf(mErrBuf, sizeof(mErrBuf), "ERROR[%s:%d]: ", file, line);
+               snprintf(mErrBuf, sizeof(mErrBuf), "ERROR: %s(%s:%i): ", function, file, line);
        } else {
                mErrBuf[0] = 0;
        }
@@ -59,12 +59,12 @@ void Logging::logError(const char* file, int line, const char* fmt, ...) {
        MUTEX_UNLOCK();
 }
 
-void Logging::logMessage(const char* fmt, ...) {
+void Logging::_logMessage(const char *function, const char *file, int line, const char *fmt, ...) {
        if (mDebug) {
                va_list args;
 
                MUTEX_LOCK();
-               strcpy(mLogBuf, "INFO: ");
+               snprintf(mLogBuf, sizeof(mLogBuf), "INFO: %s(%s:%i): ", function, file, line);
 
                va_start(args, fmt);
                vsnprintf(mLogBuf + strlen(mLogBuf), sizeof(mLogBuf) - 2 - strlen(mLogBuf), fmt, args); //  subtract 2 for \n and \0
index 09e93ff13f7a95b9f564da4c9f92e1f720df24df..a7b45239f5d81f357b783d0b97b337030c12481a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -17,10 +17,14 @@ class Logging {
 public:
        Logging(bool debug);
        ~Logging();
-       void logError(const char* file, int line, const char* fmt, ...);
-       void logMessage(const char* fmt, ...);
-       char* getLastError() {return mErrBuf;}
-       char* getLastMessage() {return mLogBuf;}
+#define logError(...) _logError(__func__, __FILE__, __LINE__, __VA_ARGS__)
+       __attribute__ ((format (printf, 5, 6)))
+       void _logError(const char *function, const char *file, int line, const char *fmt, ...);
+#define logMessage(...) _logMessage(__func__, __FILE__, __LINE__, __VA_ARGS__)
+       __attribute__ ((format (printf, 5, 6)))
+       void _logMessage(const char *function, const char *file, int line, const char *fmt, ...);
+       char *getLastError() {return mErrBuf;}
+       char *getLastMessage() {return mLogBuf;}
 
 private:
        char mErrBuf[4096]; // Arbitrarily large buffer to hold a string
@@ -29,7 +33,7 @@ private:
        pthread_mutex_t mLoggingMutex;
 };
 
-extern Logginglogg;
+extern Logging *logg;
 
 extern void handleException() __attribute__ ((noreturn));
 
index 5eef2643ab15349587dcd9e32be9ecb29d3625fc..2db332d3e2e44a6261e1c611a7e679c5a71c506d 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -109,7 +109,7 @@ static bool writeAll(const int mveUds, const char *const buf, const int pos) {
        while (written < pos) {
                size_t bytes = ::write(mveUds, buf + written, pos - written);
                if (bytes <= 0) {
-                       logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("write failed");
                        return false;
                }
                written += bytes;
index 204a57a447ace84b5db1103b25c146d551bf1698..35b0558e390bc2f0e6a89ba98d0fc385191b3392 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
index cce15c16fcdc23fe7e31cb2bc3af706a2bd37374..6818b978dc5b98347b47b76c306dbb7bb63677a5 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -59,7 +59,7 @@ void MemInfoDriver::read(Buffer *const buffer) {
        }
 
        if (!mBuf.read("/proc/meminfo")) {
-               logg->logError(__FILE__, __LINE__, "Failed to read /proc/meminfo");
+               logg->logError("Failed to read /proc/meminfo");
                handleException();
        }
 
index eb1b0417f30934481cc24be0731e35b63d09eea2..ffeaf3009e9327eeceef2b641825d22ee071219c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 74f22ee29fec7dcb776a7999e34353e1100a8a6d..04288872f515291b7b6a66a137b1f6ae6b34b949 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -38,17 +38,17 @@ bool Monitor::init() {
        mFd = epoll_create(16);
 #endif
        if (mFd < 0) {
-               logg->logMessage("%s(%s:%i): epoll_create1 failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("epoll_create1 failed");
                return false;
        }
 
 #ifndef EPOLL_CLOEXEC
-  int fdf = fcntl(mFd, F_GETFD);
-  if ((fdf == -1) || (fcntl(mFd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
-               logg->logMessage("%s(%s:%i): fcntl failed", __FUNCTION__, __FILE__, __LINE__);
-    ::close(mFd);
-    return -1;
-  }
+       int fdf = fcntl(mFd, F_GETFD);
+       if ((fdf == -1) || (fcntl(mFd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+               logg->logMessage("fcntl failed");
+               ::close(mFd);
+               return -1;
+       }
 #endif
 
        return true;
@@ -60,7 +60,7 @@ bool Monitor::add(const int fd) {
        event.data.fd = fd;
        event.events = EPOLLIN;
        if (epoll_ctl(mFd, EPOLL_CTL_ADD, fd, &event) != 0) {
-               logg->logMessage("%s(%s:%i): epoll_ctl failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("epoll_ctl failed");
                return false;
        }
 
@@ -74,7 +74,7 @@ int Monitor::wait(struct epoll_event *const events, int maxevents, int timeout)
                if (errno == EINTR) {
                        result = 0;
                } else {
-                       logg->logMessage("%s(%s:%i): epoll_wait failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("epoll_wait failed");
                }
        }
 
index 7194e0e4ca509a43782a3d17437e0c19ac7fbe8f..55368fca3e0a918fb0d41f205c71a3844772fa4a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index e75c0695779a6b830b1c86bddf306bcedd6d530b..56b25e0cfa63e440c23adea6d0fe217ce8423e48 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -108,7 +108,7 @@ bool NetDriver::doRead() {
 
 void NetDriver::start() {
        if (!doRead()) {
-               logg->logError(__FILE__, __LINE__, "Unable to read network stats");
+               logg->logError("Unable to read network stats");
                handleException();
        }
        // Initialize previous values
@@ -122,7 +122,7 @@ void NetDriver::start() {
 
 void NetDriver::read(Buffer *const buffer) {
        if (!doRead()) {
-               logg->logError(__FILE__, __LINE__, "Unable to read network stats");
+               logg->logError("Unable to read network stats");
                handleException();
        }
        super::read(buffer);
index 50ff850bfc6d97a2caaf235346eaf22e9f8aee3e..5f722800f75f89f54f496080c83e5841e52187fd 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index aa0ce4929916eb57d1637ff63acf5a07af87548b..078d2020922684f011a5f6cd66a888964b919fc7 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <netdb.h>
 #include <fcntl.h>
+#include <stddef.h>
 #endif
 
 #include "Logging.h"
@@ -78,7 +79,7 @@ OlyServerSocket::OlyServerSocket(int port) {
 #ifdef WIN32
   WSADATA wsaData;
   if (WSAStartup(0x0202, &wsaData) != 0) {
-    logg->logError(__FILE__, __LINE__, "Windows socket initialization failed");
+    logg->logError("Windows socket initialization failed");
     handleException();
   }
 #endif
@@ -97,11 +98,11 @@ OlySocket::OlySocket(int socketID) : mSocketID(socketID) {
   __a > __b ? __b : __a; \
 })
 
-OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
+OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize, const bool calculateAddrlen) {
   // Create socket
   mFDServer = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
   if (mFDServer < 0) {
-    logg->logError(__FILE__, __LINE__, "Error creating server socket");
+    logg->logError("Error creating server socket");
     handleException();
   }
 
@@ -113,19 +114,19 @@ OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
   sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
 
   // Bind the socket to an address
-  if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
-    logg->logError(__FILE__, __LINE__, "Binding of server socket failed.");
+  if (bind(mFDServer, (const struct sockaddr*)&sockaddr, calculateAddrlen ? offsetof(struct sockaddr_un, sun_path) + pathSize - 1 : sizeof(sockaddr)) < 0) {
+    logg->logError("Binding of server socket failed.");
     handleException();
   }
 
   // Listen for connections on this socket
   if (listen(mFDServer, 1) < 0) {
-    logg->logError(__FILE__, __LINE__, "Listening of server socket failed");
+    logg->logError("Listening of server socket failed");
     handleException();
   }
 }
 
-int OlySocket::connect(const char* path, const size_t pathSize) {
+int OlySocket::connect(const char* path, const size_t pathSize, const bool calculateAddrlen) {
   int fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
   if (fd < 0) {
     return -1;
@@ -138,7 +139,7 @@ int OlySocket::connect(const char* path, const size_t pathSize) {
   memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path)));
   sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
 
-  if (::connect(fd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
+  if (::connect(fd, (const struct sockaddr*)&sockaddr, calculateAddrlen ? offsetof(struct sockaddr_un, sun_path) + pathSize - 1 : sizeof(sockaddr)) < 0) {
     close(fd);
     return -1;
   }
@@ -174,11 +175,11 @@ void OlySocket::closeSocket() {
 }
 
 void OlyServerSocket::closeServerSocket() {
-  if (CLOSE_SOCKET(mFDServer) != 0) {
-    logg->logError(__FILE__, __LINE__, "Failed to close server socket.");
+  if (mFDServer > 0 && CLOSE_SOCKET(mFDServer) != 0) {
+    logg->logError("Failed to close server socket.");
     handleException();
   }
-  mFDServer = 0;
+  mFDServer = -1;
 }
 
 void OlyServerSocket::createServerSocket(int port) {
@@ -190,7 +191,7 @@ void OlyServerSocket::createServerSocket(int port) {
     family = AF_INET;
     mFDServer = socket_cloexec(PF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (mFDServer < 0) {
-      logg->logError(__FILE__, __LINE__, "Error creating server socket");
+      logg->logError("Error creating server socket");
       handleException();
     }
   }
@@ -198,10 +199,16 @@ void OlyServerSocket::createServerSocket(int port) {
   // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits
   int on = 1;
   if (setsockopt(mFDServer, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
-    logg->logError(__FILE__, __LINE__, "Setting server socket options failed");
+    logg->logError("Setting server socket reuse option failed");
     handleException();
   }
 
+  // Listen on both IPv4 and IPv6
+  on = 0;
+  if (setsockopt(mFDServer, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) != 0) {
+    logg->logMessage("setsockopt IPV6_V6ONLY failed");
+  }
+
   // Create sockaddr_in structure, ensuring non-populated fields are zero
   struct sockaddr_in6 sockaddr;
   memset((void*)&sockaddr, 0, sizeof(sockaddr));
@@ -211,13 +218,13 @@ void OlyServerSocket::createServerSocket(int port) {
 
   // Bind the socket to an address
   if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
-    logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?");
+    logg->logError("Binding of server socket on port %i failed.\nIs an instance already running or is another application using that port?", port);
     handleException();
   }
 
   // Listen for connections on this socket
   if (listen(mFDServer, 1) < 0) {
-    logg->logError(__FILE__, __LINE__, "Listening of server socket failed");
+    logg->logError("Listening of server socket failed");
     handleException();
   }
 }
@@ -227,14 +234,14 @@ void OlyServerSocket::createServerSocket(int port) {
 int OlyServerSocket::acceptConnection() {
   int socketID;
   if (mFDServer <= 0) {
-    logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket");
+    logg->logError("Attempting multiple connections on a single connection server socket or attempting to accept on a client socket");
     handleException();
   }
 
   // Accept a connection, note that this call blocks until a client connects
   socketID = accept_cloexec(mFDServer, NULL, NULL);
   if (socketID < 0) {
-    logg->logError(__FILE__, __LINE__, "Socket acceptance failed");
+    logg->logError("Socket acceptance failed");
     handleException();
   }
   return socketID;
@@ -248,7 +255,7 @@ void OlySocket::send(const char* buffer, int size) {
   while (size > 0) {
     int n = ::send(mSocketID, buffer, size, 0);
     if (n < 0) {
-      logg->logError(__FILE__, __LINE__, "Socket send error");
+      logg->logError("Socket send error");
       handleException();
     }
     size -= n;
@@ -264,7 +271,7 @@ int OlySocket::receive(char* buffer, int size) {
 
   int bytes = recv(mSocketID, buffer, size, 0);
   if (bytes < 0) {
-    logg->logError(__FILE__, __LINE__, "Socket receive error");
+    logg->logError("Socket receive error");
     handleException();
   } else if (bytes == 0) {
     logg->logMessage("Socket disconnected");
@@ -279,7 +286,7 @@ int OlySocket::receiveNBytes(char* buffer, int size) {
   while (size > 0 && buffer != NULL) {
     bytes = recv(mSocketID, buffer, size, 0);
     if (bytes < 0) {
-      logg->logError(__FILE__, __LINE__, "Socket receive error");
+      logg->logError("Socket receive error");
       handleException();
     } else if (bytes == 0) {
       logg->logMessage("Socket disconnected");
@@ -304,7 +311,7 @@ int OlySocket::receiveString(char* buffer, int size) {
     // Receive a single character
     int bytes = recv(mSocketID, &buffer[bytes_received], 1, 0);
     if (bytes < 0) {
-      logg->logError(__FILE__, __LINE__, "Socket receive error");
+      logg->logError("Socket receive error");
       handleException();
     } else if (bytes == 0) {
       logg->logMessage("Socket disconnected");
index 6b53b01fc3ee6e6c9221e219f26aca43a28882a9..757a2522f9262e237e621c9295b6342200c8cda4 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -12,7 +12,7 @@
 #include <stddef.h>
 
 #ifdef WIN32
-typedef socklen_t int;
+typedef int socklen_t;
 #else
 #include <sys/socket.h>
 #endif
@@ -20,7 +20,7 @@ typedef socklen_t int;
 class OlySocket {
 public:
 #ifndef WIN32
-  static int connect(const char* path, const size_t pathSize);
+  static int connect(const char* path, const size_t pathSize, const bool calculateAddrlen = false);
 #endif
 
   OlySocket(int socketID);
@@ -43,7 +43,7 @@ class OlyServerSocket {
 public:
   OlyServerSocket(int port);
 #ifndef WIN32
-  OlyServerSocket(const char* path, const size_t pathSize);
+  OlyServerSocket(const char* path, const size_t pathSize, const bool calculateAddrlen = false);
 #endif
   ~OlyServerSocket();
 
index 45340a27d9fa5dd26a51dad284d69281603f353a..6f40168c1ee086cfb36067278e8d7cde7759638a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 1d26beb596fae3452939b266640f3d2899362085..1525081a97a33389fa258791974127c715ed5db8 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index f127c996d43b9c6559c1ad0fd25faec11017e2a6..3b9da1dc6592d9db64b5094e06e24354c5da77c5 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -35,14 +35,14 @@ PerfBuffer::~PerfBuffer() {
 bool PerfBuffer::useFd(const int cpu, const int fd) {
        if (mFds[cpu] < 0) {
                if (mBuf[cpu] != MAP_FAILED) {
-                       logg->logMessage("%s(%s:%i): cpu %i already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__, cpu);
+                       logg->logMessage("cpu %i already online or not correctly cleaned up", cpu);
                        return false;
                }
 
                // The buffer isn't mapped yet
                mBuf[cpu] = mmap(NULL, gSessionData->mPageSize + BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                if (mBuf[cpu] == MAP_FAILED) {
-                       logg->logMessage("%s(%s:%i): mmap failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("mmap failed");
                        return false;
                }
                mFds[cpu] = fd;
@@ -50,17 +50,17 @@ bool PerfBuffer::useFd(const int cpu, const int fd) {
                // Check the version
                struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
                if (pemp->compat_version != 0) {
-                       logg->logMessage("%s(%s:%i): Incompatible perf_event_mmap_page compat_version", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("Incompatible perf_event_mmap_page compat_version");
                        return false;
                }
        } else {
                if (mBuf[cpu] == MAP_FAILED) {
-                       logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("cpu already online or not correctly cleaned up");
                        return false;
                }
 
                if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, mFds[cpu]) < 0) {
-                       logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("ioctl failed");
                        return false;
                }
        }
@@ -79,8 +79,8 @@ bool PerfBuffer::isEmpty() {
                if (mBuf[cpu] != MAP_FAILED) {
                        // Take a snapshot of the positions
                        struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
-                       const __u64 head = pemp->data_head;
-                       const __u64 tail = pemp->data_tail;
+                       const __u64 head = ACCESS_ONCE(pemp->data_head);
+                       const __u64 tail = ACCESS_ONCE(pemp->data_tail);
 
                        if (head != tail) {
                                return false;
@@ -91,42 +91,105 @@ bool PerfBuffer::isEmpty() {
        return true;
 }
 
-static void compressAndSend(const int cpu, const __u64 head, __u64 tail, const uint8_t *const b, Sender *const sender) {
-       // Pick a big size but something smaller than the chunkSize in Sender::writeData which is 100k
-       char buf[1<<16];
-       int writePos = 0;
-       const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
+bool PerfBuffer::isFull() {
+       for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+               if (mBuf[cpu] != MAP_FAILED) {
+                       // Take a snapshot of the positions
+                       struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
+                       const __u64 head = ACCESS_ONCE(pemp->data_head);
 
-       while (head > tail) {
-               writePos = 0;
-               if (!gSessionData->mLocalCapture) {
-                       buf[writePos++] = RESPONSE_APC_DATA;
+                       if (head + 2000 <= (unsigned int)BUF_SIZE) {
+                               return true;
+                       }
                }
-               // Reserve space for size
-               writePos += sizeof(uint32_t);
-               Buffer::packInt(buf, sizeof(buf), writePos, FRAME_PERF);
-               Buffer::packInt(buf, sizeof(buf), writePos, cpu);
+       }
+
+       return false;
+}
+
+class PerfFrame {
+public:
+       PerfFrame(Sender *const sender) : mSender(sender), mWritePos(-1), mCpuSizePos(-1) {}
+
+       void add(const int cpu, const __u64 head, __u64 tail, const uint8_t *const b) {
+               cpuHeader(cpu);
 
                while (head > tail) {
                        const int count = reinterpret_cast<const struct perf_event_header *>(b + (tail & BUF_MASK))->size/sizeof(uint64_t);
                        // Can this whole message be written as Streamline assumes events are not split between frames
-                       if (sizeof(buf) <= writePos + count*Buffer::MAXSIZE_PACK64) {
-                               break;
+                       if (sizeof(mBuf) <= mWritePos + count*Buffer::MAXSIZE_PACK64) {
+                               send();
+                               cpuHeader(cpu);
                        }
                        for (int i = 0; i < count; ++i) {
                                // Must account for message size
-                               Buffer::packInt64(buf, sizeof(buf), writePos, *reinterpret_cast<const uint64_t *>(b + (tail & BUF_MASK)));
+                               Buffer::packInt64(mBuf, sizeof(mBuf), mWritePos, *reinterpret_cast<const uint64_t *>(b + (tail & BUF_MASK)));
                                tail += sizeof(uint64_t);
                        }
                }
+       }
+
+       void send() {
+               if (mWritePos > 0) {
+                       writeFrameSize();
+                       mSender->writeData(mBuf, mWritePos, RESPONSE_APC_DATA);
+                       mWritePos = -1;
+                       mCpuSizePos = -1;
+               }
+       }
 
-               // Write size
-               Buffer::writeLEInt(reinterpret_cast<unsigned char *>(buf + typeLength), writePos - typeLength - sizeof(uint32_t));
-               sender->writeData(buf, writePos, RESPONSE_APC_DATA);
+private:
+       void writeFrameSize() {
+               writeCpuSize();
+               const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
+               Buffer::writeLEInt(reinterpret_cast<unsigned char *>(mBuf + typeLength), mWritePos - typeLength - sizeof(uint32_t));
        }
-}
+
+       void frameHeader() {
+               if (mWritePos < 0) {
+                       mWritePos = 0;
+                       mCpuSizePos = -1;
+                       if (!gSessionData->mLocalCapture) {
+                               mBuf[mWritePos++] = RESPONSE_APC_DATA;
+                       }
+                       // Reserve space for frame size
+                       mWritePos += sizeof(uint32_t);
+                       Buffer::packInt(mBuf, sizeof(mBuf), mWritePos, FRAME_PERF);
+               }
+       }
+
+       void writeCpuSize() {
+               if (mCpuSizePos >= 0) {
+                       Buffer::writeLEInt(reinterpret_cast<unsigned char *>(mBuf + mCpuSizePos), mWritePos - mCpuSizePos - sizeof(uint32_t));
+               }
+       }
+
+       void cpuHeader(const int cpu) {
+               if (sizeof(mBuf) <= mWritePos + Buffer::MAXSIZE_PACK32 + sizeof(uint32_t)) {
+                       send();
+               }
+               frameHeader();
+               writeCpuSize();
+               Buffer::packInt(mBuf, sizeof(mBuf), mWritePos, cpu);
+               mCpuSizePos = mWritePos;
+               // Reserve space for cpu size
+               mWritePos += sizeof(uint32_t);
+       }
+
+       // Pick a big size but something smaller than the chunkSize in Sender::writeData which is 100k
+       char mBuf[1<<16];
+       Sender *const mSender;
+       int mWritePos;
+       int mCpuSizePos;
+
+       // Intentionally unimplemented
+       PerfFrame(const PerfFrame &);
+       PerfFrame& operator=(const PerfFrame &);
+};
 
 bool PerfBuffer::send(Sender *const sender) {
+       PerfFrame frame(sender);
+
        for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
                if (mBuf[cpu] == MAP_FAILED) {
                        continue;
@@ -134,12 +197,12 @@ bool PerfBuffer::send(Sender *const sender) {
 
                // Take a snapshot of the positions
                struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
-               const __u64 head = pemp->data_head;
-               const __u64 tail = pemp->data_tail;
+               const __u64 head = ACCESS_ONCE(pemp->data_head);
+               const __u64 tail = ACCESS_ONCE(pemp->data_tail);
 
                if (head > tail) {
                        const uint8_t *const b = static_cast<uint8_t *>(mBuf[cpu]) + gSessionData->mPageSize;
-                       compressAndSend(cpu, head, tail, b, sender);
+                       frame.add(cpu, head, tail, b);
 
                        // Update tail with the data read
                        pemp->data_tail = head;
@@ -150,9 +213,11 @@ bool PerfBuffer::send(Sender *const sender) {
                        mBuf[cpu] = MAP_FAILED;
                        mDiscard[cpu] = false;
                        mFds[cpu] = -1;
-                       logg->logMessage("%s(%s:%i): Unmaped cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
+                       logg->logMessage("Unmaped cpu %i", cpu);
                }
        }
 
+       frame.send();
+
        return true;
 }
index 25a10625a9e8006b255b4c4a0183e741b0620e9e..a2d0e9b447256db4219a9d21e6fd2bdaabfe223a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -24,6 +24,7 @@ public:
        bool useFd(const int cpu, const int fd);
        void discard(const int cpu);
        bool isEmpty();
+       bool isFull();
        bool send(Sender *const sender);
 
 private:
index ee90284cee41434cef36690e753a5089039092b4..796ee7564c66b0cc1391d88ce3da078da5ee589c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -40,24 +40,25 @@ struct gator_cpu {
 
 // From gator_main.c
 static const struct gator_cpu gator_cpus[] = {
-       { 0xb36, "ARM1136",      "ARM_ARM11",        3 },
-       { 0xb56, "ARM1156",      "ARM_ARM11",        3 },
-       { 0xb76, "ARM1176",      "ARM_ARM11",        3 },
-       { 0xb02, "ARM11MPCore",  "ARM_ARM11MPCore",  3 },
-       { 0xc05, "Cortex-A5",    "ARMv7_Cortex_A5",  2 },
-       { 0xc07, "Cortex-A7",    "ARMv7_Cortex_A7",  4 },
-       { 0xc08, "Cortex-A8",    "ARMv7_Cortex_A8",  4 },
-       { 0xc09, "Cortex-A9",    "ARMv7_Cortex_A9",  6 },
-       { 0xc0f, "Cortex-A15",   "ARMv7_Cortex_A15", 6 },
-       { 0xc0e, "Cortex-A17",   "ARMv7_Cortex_A17", 6 },
-       { 0x00f, "Scorpion",     "Scorpion",         4 },
-       { 0x02d, "ScorpionMP",   "ScorpionMP",       4 },
-       { 0x049, "KraitSIM",     "Krait",            4 },
-       { 0x04d, "Krait",        "Krait",            4 },
-       { 0x06f, "Krait S4 Pro", "Krait",            4 },
-       { 0xd03, "Cortex-A53",   "ARM_Cortex-A53",   6 },
-       { 0xd07, "Cortex-A57",   "ARM_Cortex-A57",   6 },
-       { 0xd0f, "AArch64",      "ARM_AArch64",      6 },
+       { 0x41b36, "ARM1136",      "ARM_ARM11",        3 },
+       { 0x41b56, "ARM1156",      "ARM_ARM11",        3 },
+       { 0x41b76, "ARM1176",      "ARM_ARM11",        3 },
+       { 0x41b02, "ARM11MPCore",  "ARM_ARM11MPCore",  3 },
+       { 0x41c05, "Cortex-A5",    "ARMv7_Cortex_A5",  2 },
+       { 0x41c07, "Cortex-A7",    "ARMv7_Cortex_A7",  4 },
+       { 0x41c08, "Cortex-A8",    "ARMv7_Cortex_A8",  4 },
+       { 0x41c09, "Cortex-A9",    "ARMv7_Cortex_A9",  6 },
+       { 0x41c0f, "Cortex-A15",   "ARMv7_Cortex_A15", 6 },
+       { 0x41c0d, "Cortex-A17",   "ARMv7_Cortex_A17", 6 },
+       { 0x41c0e, "Cortex-A17",   "ARMv7_Cortex_A17", 6 },
+       { 0x5100f, "Scorpion",     "Scorpion",         4 },
+       { 0x5102d, "ScorpionMP",   "ScorpionMP",       4 },
+       { 0x51049, "KraitSIM",     "Krait",            4 },
+       { 0x5104d, "Krait",        "Krait",            4 },
+       { 0x5106f, "Krait S4 Pro", "Krait",            4 },
+       { 0x41d03, "Cortex-A53",   "ARM_Cortex-A53",   6 },
+       { 0x41d07, "Cortex-A57",   "ARM_Cortex-A57",   6 },
+       { 0x41d08, "Cortex-A72",   "ARM_Cortex-A72",   6 },
 };
 
 static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-";
@@ -69,17 +70,19 @@ struct uncore_counter {
        // gatorfs event name
        const char *const gatorName;
        const int count;
+       const bool hasCyclesCounter;
 };
 
 static const struct uncore_counter uncore_counters[] = {
-       { "CCI_400", "CCI_400", 4 },
-       { "CCI_400-r1", "CCI_400-r1", 4 },
-       { "ccn", "ARM_CCN_5XX", 8 },
+       { "CCI_400",    "CCI_400",     4, true },
+       { "CCI_400-r1", "CCI_400-r1",  4, true },
+       { "CCI_500",    "CCI_500",     8, false },
+       { "ccn",        "ARM_CCN_5XX", 8, true },
 };
 
 class PerfCounter : public DriverCounter {
 public:
-       PerfCounter(DriverCounter *next, const char *name, uint32_t type, uint64_t config, bool perCpu) : DriverCounter(next, name), mType(type), mCount(0), mConfig(config), mPerCpu(perCpu) {}
+       PerfCounter(DriverCounter *next, const char *name, uint32_t type, uint64_t config, uint64_t sampleType, uint64_t flags) : DriverCounter(next, name), mType(type), mConfig(config), mSampleType(sampleType), mFlags(flags), mCount(0) {}
 
        ~PerfCounter() {
        }
@@ -89,13 +92,41 @@ public:
        void setCount(const int count) { mCount = count; }
        uint64_t getConfig() const { return mConfig; }
        void setConfig(const uint64_t config) { mConfig = config; }
-       bool isPerCpu() const { return mPerCpu; }
+       uint64_t getSampleType() const { return mSampleType; }
+       uint64_t getFlags() const { return mFlags; }
+       virtual void read(Buffer *const, const int) {}
 
 private:
        const uint32_t mType;
-       int mCount;
        uint64_t mConfig;
-       bool mPerCpu;
+       const uint64_t mSampleType;
+       const uint64_t mFlags;
+       int mCount;
+
+       // Intentionally undefined
+       PerfCounter(const PerfCounter &);
+       PerfCounter &operator=(const PerfCounter &);
+};
+
+class CPUFreqDriver : public PerfCounter {
+public:
+       CPUFreqDriver(DriverCounter *next, uint64_t id) : PerfCounter(next, "Linux_power_cpu_freq", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_RAW, PERF_GROUP_LEADER | PERF_GROUP_PER_CPU) {}
+
+       void read(Buffer *const buffer, const int cpu) {
+               char buf[64];
+
+               snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/cpufreq/cpuinfo_cur_freq", cpu);
+               int64_t freq;
+               if (DriverSource::readInt64Driver(buf, &freq) != 0) {
+                       freq = 0;
+               }
+               buffer->perfCounter(cpu, getKey(), 1000*freq);
+       }
+
+private:
+       // Intentionally undefined
+       CPUFreqDriver(const CPUFreqDriver &);
+       CPUFreqDriver &operator=(const CPUFreqDriver &);
 };
 
 PerfDriver::PerfDriver() : mIsSetup(false), mLegacySupport(false) {
@@ -108,27 +139,32 @@ void PerfDriver::addCpuCounters(const char *const counterName, const int type, c
        int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
        char *name = new char[len];
        snprintf(name, len, "%s_ccnt", counterName);
-       setCounters(new PerfCounter(getCounters(), name, type, -1, true));
+       setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU));
 
        for (int j = 0; j < numCounters; ++j) {
                len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
                name = new char[len];
                snprintf(name, len, "%s_cnt%d", counterName, j);
-               setCounters(new PerfCounter(getCounters(), name, type, -1, true));
+               setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU));
        }
 }
 
-void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters) {
-       int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
-       char *name = new char[len];
-       snprintf(name, len, "%s_ccnt", counterName);
-       setCounters(new PerfCounter(getCounters(), name, type, -1, false));
+void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters, const bool hasCyclesCounter) {
+       int len;
+       char *name;
+
+       if (hasCyclesCounter) {
+               len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
+               name = new char[len];
+               snprintf(name, len, "%s_ccnt", counterName);
+               setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, 0));
+       }
 
        for (int j = 0; j < numCounters; ++j) {
                len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
                name = new char[len];
                snprintf(name, len, "%s_cnt%d", counterName, j);
-               setCounters(new PerfCounter(getCounters(), name, type, -1, false));
+               setCounters(new PerfCounter(getCounters(), name, type, -1, PERF_SAMPLE_READ, 0));
        }
 }
 
@@ -136,18 +172,18 @@ bool PerfDriver::setup() {
        // Check the kernel version
        int release[3];
        if (!getLinuxVersion(release)) {
-               logg->logMessage("%s(%s:%i): getLinuxVersion failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("getLinuxVersion failed");
                return false;
        }
 
        if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) {
-               logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("Unsupported kernel version");
                return false;
        }
        mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0);
 
        if (access(EVENTS_PATH, R_OK) != 0) {
-               logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER enabled?", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage(EVENTS_PATH " does not exist, is CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER enabled?");
                return false;
        }
 
@@ -155,7 +191,7 @@ bool PerfDriver::setup() {
        bool foundCpu = false;
        DIR *dir = opendir(PERF_DEVICES);
        if (dir == NULL) {
-               logg->logMessage("%s(%s:%i): opendif failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("opendir failed");
                return false;
        }
 
@@ -198,7 +234,7 @@ bool PerfDriver::setup() {
                        }
 
                        logg->logMessage("Adding uncore counters for %s", uncore_counters[i].gatorName);
-                       addUncoreCounters(uncore_counters[i].gatorName, type, uncore_counters[i].count);
+                       addUncoreCounters(uncore_counters[i].gatorName, type, uncore_counters[i].count, uncore_counters[i].hasCyclesCounter);
                }
        }
        closedir(dir);
@@ -216,13 +252,11 @@ bool PerfDriver::setup() {
                }
        }
 
-       /*
        if (!foundCpu) {
-               // If all else fails, use the perf architected counters
-               // 9 because that's how many are in events-Perf-Hardware.xml - assume they can all be enabled at once
-               addCpuCounters("Perf_Hardware", PERF_TYPE_HARDWARE, 9);
+               // If all else fails, use the ARM architected counters
+               logg->logMessage("Using Other cpu");
+               addCpuCounters("Other", PERF_TYPE_RAW, 6);
        }
-       */
 
        // Add supported software counters
        long long id;
@@ -230,20 +264,25 @@ bool PerfDriver::setup() {
 
        id = getTracepointId("irq/softirq_exit", &printb);
        if (id >= 0) {
-               setCounters(new PerfCounter(getCounters(), "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true));
+               setCounters(new PerfCounter(getCounters(), "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU));
        }
 
        id = getTracepointId("irq/irq_handler_exit", &printb);
        if (id >= 0) {
-               setCounters(new PerfCounter(getCounters(), "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true));
+               setCounters(new PerfCounter(getCounters(), "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU));
        }
 
        id = getTracepointId(SCHED_SWITCH, &printb);
        if (id >= 0) {
-               setCounters(new PerfCounter(getCounters(), "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true));
+               setCounters(new PerfCounter(getCounters(), "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU));
+       }
+
+       id = getTracepointId(CPU_FREQUENCY, &printb);
+       if (id >= 0) {
+               setCounters(new CPUFreqDriver(getCounters(), id));
        }
 
-       setCounters(new PerfCounter(getCounters(), "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false));
+       setCounters(new PerfCounter(getCounters(), "Linux_cpu_wait_contention", TYPE_DERIVED, -1, 0, 0));
 
        //Linux_cpu_wait_io
 
@@ -254,7 +293,7 @@ bool PerfDriver::setup() {
 bool PerfDriver::summary(Buffer *const buffer) {
        struct utsname utsname;
        if (uname(&utsname) != 0) {
-               logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("uname failed");
                return false;
        }
 
@@ -263,25 +302,26 @@ bool PerfDriver::summary(Buffer *const buffer) {
 
        struct timespec ts;
        if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
-               logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("clock_gettime failed");
                return false;
        }
        const int64_t timestamp = (int64_t)ts.tv_sec * NS_PER_S + ts.tv_nsec;
 
        const uint64_t monotonicStarted = getTime();
        gSessionData->mMonotonicStarted = monotonicStarted;
+       const uint64_t currTime = 0;//getTime() - gSessionData->mMonotonicStarted;
 
-       buffer->summary(monotonicStarted, timestamp, monotonicStarted, monotonicStarted, buf);
+       buffer->summary(currTime, timestamp, monotonicStarted, monotonicStarted, buf);
 
        for (int i = 0; i < gSessionData->mCores; ++i) {
-               coreName(monotonicStarted, buffer, i);
+               coreName(currTime, buffer, i);
        }
-       buffer->commit(monotonicStarted);
+       buffer->commit(currTime);
 
        return true;
 }
 
-void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const int cpu) {
+void PerfDriver::coreName(const uint64_t currTime, Buffer *const buffer, const int cpu) {
        // Don't send information on a cpu we know nothing about
        if (gSessionData->mCpuIds[cpu] == -1) {
                return;
@@ -293,8 +333,8 @@ void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const
                        break;
                }
        }
-       if (gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) {
-               buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], gator_cpus[j].core_name);
+       if (j < ARRAY_LENGTH(gator_cpus) && gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) {
+               buffer->coreName(currTime, cpu, gSessionData->mCpuIds[cpu], gator_cpus[j].core_name);
        } else {
                char buf[32];
                if (gSessionData->mCpuIds[cpu] == -1) {
@@ -302,7 +342,7 @@ void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const
                } else {
                        snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[cpu]);
                }
-               buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], buf);
+               buffer->coreName(currTime, cpu, gSessionData->mCpuIds[cpu], buf);
        }
 }
 
@@ -325,8 +365,17 @@ void PerfDriver::setupCounter(Counter &counter) {
 bool PerfDriver::enable(const uint64_t currTime, PerfGroup *const group, Buffer *const buffer) const {
        for (PerfCounter *counter = static_cast<PerfCounter *>(getCounters()); counter != NULL; counter = static_cast<PerfCounter *>(counter->getNext())) {
                if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) {
-                       if (!group->add(currTime, buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), counter->getCount() > 0 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP : 0, counter->isPerCpu() ? PERF_GROUP_PER_CPU : 0)) {
-                               logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__);
+                       int count = counter->getCount();
+                       uint64_t sampleType = counter->getSampleType();
+                       if (sampleType & PERF_SAMPLE_RAW) {
+                               // If raw is enabled, every sample is needed
+                               count = 1;
+                       }
+                       if (!group->add(currTime, buffer, counter->getKey(), counter->getType(), counter->getConfig(), count,
+                                       // use getCount instead of count as EBS counters need TID and IP but RAW tracepoints don't
+                                       (counter->getCount() > 0 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP : 0) | sampleType,
+                                       counter->getFlags())) {
+                               logg->logMessage("PerfGroup::add failed");
                                return false;
                        }
                }
@@ -335,15 +384,24 @@ bool PerfDriver::enable(const uint64_t currTime, PerfGroup *const group, Buffer
        return true;
 }
 
+void PerfDriver::read(Buffer *const buffer, const int cpu) {
+       for (PerfCounter *counter = static_cast<PerfCounter *>(getCounters()); counter != NULL; counter = static_cast<PerfCounter *>(counter->getNext())) {
+               if (!counter->isEnabled()) {
+                       continue;
+               }
+               counter->read(buffer, cpu);
+       }
+}
+
 long long PerfDriver::getTracepointId(const char *const name, DynBuf *const printb) {
        if (!printb->printf(EVENTS_PATH "/%s/id", name)) {
-               logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::printf failed");
                return -1;
        }
 
        int64_t result;
        if (DriverSource::readInt64Driver(printb->getBuf(), &result) != 0) {
-               logg->logMessage("%s(%s:%i): DriverSource::readInt64Driver failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DriverSource::readInt64Driver failed");
                return -1;
        }
 
index 846203a9e18b3def479ea20c58e3cc488d384fb6..95b42bfa30c00360813532c3a7a16fde3a452e8f 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -19,6 +19,7 @@
 
 #define SCHED_SWITCH "sched/sched_switch"
 #define CPU_IDLE "power/cpu_idle"
+#define CPU_FREQUENCY "power/cpu_frequency"
 
 class Buffer;
 class DynBuf;
@@ -33,18 +34,19 @@ public:
 
        bool setup();
        bool summary(Buffer *const buffer);
-       void coreName(const uint32_t startTime, Buffer *const buffer, const int cpu);
+       void coreName(const uint64_t currTime, Buffer *const buffer, const int cpu);
        bool isSetup() const { return mIsSetup; }
 
        void setupCounter(Counter &counter);
 
        bool enable(const uint64_t currTime, PerfGroup *const group, Buffer *const buffer) const;
+       void read(Buffer *const buffer, const int cpu);
 
        static long long getTracepointId(const char *const name, DynBuf *const printb);
 
 private:
        void addCpuCounters(const char *const counterName, const int type, const int numCounters);
-       void addUncoreCounters(const char *const counterName, const int type, const int numCounters);
+       void addUncoreCounters(const char *const counterName, const int type, const int numCounters, const bool hasCyclesCounter);
 
        bool mIsSetup;
        bool mLegacySupport;
index 4fd960a9058c5ebcd194b20fbb5f70979efbee34..cfc62e4cc77e99549cca4e345a5a48cc9c221ea8 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
 #include <unistd.h>
 
 #include "Buffer.h"
+#include "DynBuf.h"
 #include "Logging.h"
 #include "Monitor.h"
 #include "PerfBuffer.h"
 #include "SessionData.h"
 
+static const int schedSwitchKey = getEventKey();
+static const int clockKey = getEventKey();
+
 #define DEFAULT_PEA_ARGS(pea, additionalSampleType) \
        pea.size = sizeof(pea); \
        /* Emit time, read_format below, group leader id, and raw tracepoint info */ \
        pea.sample_type = (gSessionData->perf.getLegacySupport() \
-                                                                                ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_ID \
-                                                                                : PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER ) | additionalSampleType; \
+                          ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_ID \
+                          : PERF_SAMPLE_IDENTIFIER ) | PERF_SAMPLE_TIME | additionalSampleType; \
        /* Emit emit value in group format */ \
        pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \
        /* start out disabled */ \
@@ -49,11 +53,12 @@ static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t p
        return fd;
 }
 
-PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) {
+PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb), mSchedSwitchId(-1) {
        memset(&mAttrs, 0, sizeof(mAttrs));
-       memset(&mPerCpu, 0, sizeof(mPerCpu));
+       memset(&mFlags, 0, sizeof(mFlags));
        memset(&mKeys, -1, sizeof(mKeys));
        memset(&mFds, -1, sizeof(mFds));
+       memset(&mLeaders, -1, sizeof(mLeaders));
 }
 
 PerfGroup::~PerfGroup() {
@@ -64,7 +69,7 @@ PerfGroup::~PerfGroup() {
        }
 }
 
-bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
+int PerfGroup::doAdd(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
        int i;
        for (i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
                if (mKeys[i] < 0) {
@@ -73,8 +78,8 @@ bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key
        }
 
        if (i >= ARRAY_LENGTH(mKeys)) {
-               logg->logMessage("%s(%s:%i): Too many counters", __FUNCTION__, __FILE__, __LINE__);
-               return false;
+               logg->logMessage("Too many counters");
+               return -1;
        }
 
        DEFAULT_PEA_ARGS(mAttrs[i], sampleType);
@@ -82,121 +87,230 @@ bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key
        mAttrs[i].config = config;
        mAttrs[i].sample_period = sample;
        // always be on the CPU but only a group leader can be pinned
-       mAttrs[i].pinned = (i == 0 ? 1 : 0);
+       mAttrs[i].pinned = (flags & PERF_GROUP_LEADER ? 1 : 0);
        mAttrs[i].mmap = (flags & PERF_GROUP_MMAP ? 1 : 0);
        mAttrs[i].comm = (flags & PERF_GROUP_COMM ? 1 : 0);
        mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0);
        mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0);
        mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0);
-       mPerCpu[i] = (flags & PERF_GROUP_PER_CPU);
+       mFlags[i] = flags;
 
        mKeys[i] = key;
 
-       buffer->pea(currTime, &mAttrs[i], key);
+       buffer->marshalPea(currTime, &mAttrs[i], key);
+
+       return i;
+}
+
+/* Counters from different hardware PMUs need to be in different
+ * groups. Software counters can be in the same group as the CPU and
+ * should be marked as PERF_GROUP_CPU. The big and little clusters can
+ * be in the same group as only one or the other will be available on
+ * a given CPU.
+ */
+int PerfGroup::getEffectiveType(const int type, const int flags) {
+       const int effectiveType = flags & PERF_GROUP_CPU ? (int)PERF_TYPE_HARDWARE : type;
+       if (effectiveType >= ARRAY_LENGTH(mLeaders)) {
+               logg->logError("perf type is too large, please increase the size of PerfGroup::mLeaders");
+               handleException();
+       }
+       return effectiveType;
+}
+
+bool PerfGroup::createCpuGroup(const uint64_t currTime, Buffer *const buffer) {
+       if (mSchedSwitchId < 0) {
+               DynBuf b;
+               mSchedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &b);
+               if (mSchedSwitchId < 0) {
+                       logg->logMessage("Unable to read sched_switch id");
+                       return false;
+               }
+       }
+
+       mLeaders[PERF_TYPE_HARDWARE] = doAdd(currTime, buffer, schedSwitchKey, PERF_TYPE_TRACEPOINT, mSchedSwitchId, 1, PERF_SAMPLE_READ | PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU | PERF_GROUP_LEADER | PERF_GROUP_CPU);
+       if (mLeaders[PERF_TYPE_HARDWARE] < 0) {
+               return false;
+       }
+
+       if (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && doAdd(currTime, buffer, clockKey, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_READ, PERF_GROUP_PER_CPU | PERF_GROUP_CPU) < 0) {
+               return false;
+       }
 
        return true;
 }
 
+bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
+       const int effectiveType = getEffectiveType(type, flags);
+
+       // Does a group exist for this already?
+       if (!(flags & PERF_GROUP_LEADER) && mLeaders[effectiveType] < 0) {
+               // Create it
+               if (effectiveType == PERF_TYPE_HARDWARE) {
+                       if (!createCpuGroup(currTime, buffer)) {
+                               return false;
+                       }
+               } else {
+                       // Non-CPU PMUs are sampled every 100ms for Sample Rate: None and EBS, otherwise they would never be sampled
+                       const uint64_t timeout = gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS ? 1000000000UL / gSessionData->mSampleRate : 100000000UL;
+                       // PERF_SAMPLE_TID | PERF_SAMPLE_IP aren't helpful on non-CPU or 'uncore' PMUs - which CPU is the right one to sample? But removing it causes problems, remove it later.
+                       mLeaders[effectiveType] = doAdd(currTime, buffer, clockKey, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, timeout, PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_READ, PERF_GROUP_LEADER);
+                       if (mLeaders[effectiveType] < 0) {
+                               return false;
+                       }
+               }
+       }
+
+       if (!(flags & PERF_GROUP_LEADER) && effectiveType != PERF_TYPE_HARDWARE && (flags & PERF_GROUP_PER_CPU)) {
+               logg->logError("'uncore' counters are not permitted to be per-cpu");
+               handleException();
+       }
+
+       return doAdd(currTime, buffer, key, type, config, sample, sampleType, flags) >= 0;
+}
+
 int PerfGroup::prepareCPU(const int cpu, Monitor *const monitor) {
-       logg->logMessage("%s(%s:%i): Onlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
+       logg->logMessage("Onlining cpu %i", cpu);
 
        for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
                if (mKeys[i] < 0) {
                        continue;
                }
 
-               if ((cpu != 0) && !mPerCpu[i]) {
+               if ((cpu != 0) && !(mFlags[i] & PERF_GROUP_PER_CPU)) {
                        continue;
                }
 
-               const int offset = i * gSessionData->mCores;
-               if (mFds[cpu + offset] >= 0) {
-                       logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
+               const int offset = i * gSessionData->mCores + cpu;
+               if (mFds[offset] >= 0) {
+                       logg->logMessage("cpu already online or not correctly cleaned up");
                        return PG_FAILURE;
                }
 
-               logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: 0x%llx pinned: %i mmap: %i comm: %i freq: %i task: %i sample_id_all: %i", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all);
-               mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT);
-               if (mFds[cpu + offset] < 0) {
-                       logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno));
+               logg->logMessage("perf_event_open cpu: %i type: %i config: %lli sample: %lli sample_type: 0x%llx pinned: %lli mmap: %lli comm: %lli freq: %lli task: %lli sample_id_all: %lli", cpu, mAttrs[i].type, mAttrs[i].config, mAttrs[i].sample_period, mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all);
+               mFds[offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, mAttrs[i].pinned ? -1 : mFds[mLeaders[getEffectiveType(mAttrs[i].type, mFlags[i])] * gSessionData->mCores + cpu], mAttrs[i].pinned ? 0 : PERF_FLAG_FD_OUTPUT);
+               if (mFds[offset] < 0) {
+                       logg->logMessage("failed %s", strerror(errno));
                        if (errno == ENODEV) {
+                               // The core is offline
                                return PG_CPU_OFFLINE;
                        }
+#ifndef USE_STRICTER_CHECK
                        continue;
+#else
+                       if (errno == ENOENT) {
+                               // This event doesn't apply to this CPU but should apply to a different one, ex bL
+                               continue;
+                       }
+                       logg->logMessage("perf_event_open failed");
+                       return PG_FAILURE;
+#endif
                }
 
-               if (!mPb->useFd(cpu, mFds[cpu + offset])) {
-                       logg->logMessage("%s(%s:%i): PerfBuffer::useFd failed", __FUNCTION__, __FILE__, __LINE__);
+               if (!mPb->useFd(cpu, mFds[offset])) {
+                       logg->logMessage("PerfBuffer::useFd failed");
                        return PG_FAILURE;
                }
 
 
-               if (!monitor->add(mFds[cpu + offset])) {
-                 logg->logMessage("%s(%s:%i): Monitor::add failed", __FUNCTION__, __FILE__, __LINE__);
-                 return PG_FAILURE;
+               if (!monitor->add(mFds[offset])) {
+                       logg->logMessage("Monitor::add failed");
+                       return PG_FAILURE;
                }
        }
 
        return PG_SUCCESS;
 }
 
-int PerfGroup::onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer) {
-       __u64 ids[ARRAY_LENGTH(mKeys)];
-       int coreKeys[ARRAY_LENGTH(mKeys)];
-       int idCount = 0;
+static bool readAndSend(const uint64_t currTime, Buffer *const buffer, const int fd, const int keyCount, const int *const keys) {
+       char buf[1024];
+       ssize_t bytes = read(fd, buf, sizeof(buf));
+       if (bytes < 0) {
+               logg->logMessage("read failed");
+               return false;
+       }
+       buffer->marshalKeysOld(currTime, keyCount, keys, bytes, buf);
 
-       for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
-               const int fd = mFds[cpu + i * gSessionData->mCores];
-               if (fd < 0) {
-                       continue;
-               }
+       return true;
+}
 
-               coreKeys[idCount] = mKeys[i];
-               if (!gSessionData->perf.getLegacySupport() && ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 &&
-                               // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works
-                               ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) {
-                       logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
-                       return 0;
-               }
-               ++idCount;
-       }
+int PerfGroup::onlineCPU(const uint64_t currTime, const int cpu, const bool enable, Buffer *const buffer) {
+       bool addedEvents = false;
 
        if (!gSessionData->perf.getLegacySupport()) {
-               buffer->keys(currTime, idCount, ids, coreKeys);
+               int idCount = 0;
+               int coreKeys[ARRAY_LENGTH(mKeys)];
+               __u64 ids[ARRAY_LENGTH(mKeys)];
+
+               for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
+                       const int fd = mFds[cpu + i * gSessionData->mCores];
+                       if (fd < 0) {
+                               continue;
+                       }
+
+                       coreKeys[idCount] = mKeys[i];
+                       if (ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 &&
+                                       // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works
+                                       ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) {
+                               logg->logMessage("ioctl failed");
+                               return 0;
+                       }
+                       ++idCount;
+                       addedEvents = true;
+               }
+
+               buffer->marshalKeys(currTime, idCount, ids, coreKeys);
        } else {
-               char buf[1024];
-               ssize_t bytes = read(mFds[cpu], buf, sizeof(buf));
-               if (bytes < 0) {
-                       logg->logMessage("read failed");
-                       return 0;
+               int idCounts[ARRAY_LENGTH(mLeaders)] = { 0 };
+               int coreKeys[ARRAY_LENGTH(mLeaders)][ARRAY_LENGTH(mKeys)];
+               for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
+                       const int fd = mFds[cpu + i * gSessionData->mCores];
+                       if (fd < 0) {
+                               continue;
+                       }
+
+                       const int effectiveType = getEffectiveType(mAttrs[i].type, mFlags[i]);
+                       if (mAttrs[i].pinned && mLeaders[effectiveType] != i) {
+                               if (!readAndSend(currTime, buffer, fd, 1, mKeys + i)) {
+                                       return 0;
+                               }
+                       } else {
+                               coreKeys[effectiveType][idCounts[effectiveType]] = mKeys[i];
+                               ++idCounts[effectiveType];
+                               addedEvents = true;
+                       }
+               }
+
+               for (int i = 0; i < ARRAY_LENGTH(mLeaders); ++i) {
+                       if (idCounts[i] > 0 && !readAndSend(currTime, buffer, mFds[mLeaders[i] * gSessionData->mCores + cpu], idCounts[i], coreKeys[i])) {
+                                       return 0;
+                       }
                }
-               buffer->keysOld(currTime, idCount, coreKeys, bytes, buf);
        }
 
-       if (start) {
+       if (enable) {
                for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
                        int offset = i * gSessionData->mCores + cpu;
                        if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_ENABLE, 0) < 0) {
-                               logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
+                               logg->logMessage("ioctl failed");
                                return 0;
                        }
                }
        }
 
-       if (idCount == 0) {
-               logg->logMessage("%s(%s:%i): no events came online", __FUNCTION__, __FILE__, __LINE__);
+       if (!addedEvents) {
+               logg->logMessage("no events came online");
        }
 
-       return idCount;
+       return 1;
 }
 
 bool PerfGroup::offlineCPU(const int cpu) {
-       logg->logMessage("%s(%s:%i): Offlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
+       logg->logMessage("Offlining cpu %i", cpu);
 
-       for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
+       for (int i = ARRAY_LENGTH(mKeys) - 1; i >= 0; --i) {
                int offset = i * gSessionData->mCores + cpu;
                if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_DISABLE, 0) < 0) {
-                       logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("ioctl failed");
                        return false;
                }
        }
@@ -204,7 +318,7 @@ bool PerfGroup::offlineCPU(const int cpu) {
        // Mark the buffer so that it will be released next time it's read
        mPb->discard(cpu);
 
-       for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
+       for (int i = ARRAY_LENGTH(mKeys) - 1; i >= 0; --i) {
                if (mKeys[i] < 0) {
                        continue;
                }
@@ -222,7 +336,7 @@ bool PerfGroup::offlineCPU(const int cpu) {
 bool PerfGroup::start() {
        for (int pos = 0; pos < ARRAY_LENGTH(mFds); ++pos) {
                if (mFds[pos] >= 0 && ioctl(mFds[pos], PERF_EVENT_IOC_ENABLE, 0) < 0) {
-                       logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("ioctl failed");
                        goto fail;
                }
        }
index f7b3d725bac71d924ca466f11549ce9ddea669b8..f30d3a6a9c6812d8ae14e77c4112fc625756ad44 100644 (file)
@@ -1,5 +1,5 @@
  /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -27,6 +27,8 @@ enum PerfGroupFlags {
        PERF_GROUP_TASK          = 1 << 3,
        PERF_GROUP_SAMPLE_ID_ALL = 1 << 4,
        PERF_GROUP_PER_CPU       = 1 << 5,
+       PERF_GROUP_LEADER        = 1 << 6,
+       PERF_GROUP_CPU           = 1 << 7,
 };
 
 enum {
@@ -40,22 +42,29 @@ public:
        PerfGroup(PerfBuffer *const pb);
        ~PerfGroup();
 
+       bool createCpuGroup(const uint64_t currTime, Buffer *const buffer);
        bool add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags);
        // Safe to call concurrently
        int prepareCPU(const int cpu, Monitor *const monitor);
        // Not safe to call concurrently. Returns the number of events enabled
-       int onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer);
+       int onlineCPU(const uint64_t currTime, const int cpu, const bool enable, Buffer *const buffer);
        bool offlineCPU(int cpu);
        bool start();
        void stop();
 
 private:
-       // +1 for the group leader
-       struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1];
-       bool mPerCpu[MAX_PERFORMANCE_COUNTERS + 1];
-       int mKeys[MAX_PERFORMANCE_COUNTERS + 1];
-       int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)];
+       int getEffectiveType(const int type, const int flags);
+       int doAdd(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags);
+
+       // 2* to be conservative for sched_switch, cpu_idle, hrtimer and non-CPU groups
+       struct perf_event_attr mAttrs[2*MAX_PERFORMANCE_COUNTERS];
        PerfBuffer *const mPb;
+       int mFlags[2*MAX_PERFORMANCE_COUNTERS];
+       int mKeys[2*MAX_PERFORMANCE_COUNTERS];
+       int mFds[NR_CPUS * (2*MAX_PERFORMANCE_COUNTERS)];
+       // Offset in mAttrs, mFlags and mKeys of the group leaders for each perf type
+       int mLeaders[16];
+       int mSchedSwitchId;
 
        // Intentionally undefined
        PerfGroup(const PerfGroup &);
index 193b7789a290bb1583db307568ec94a2043599ed..2c45de8e06e9bdf6beb72130eb74796f184388ea 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
 
 extern Child *child;
 
+static const int cpuIdleKey = getEventKey();
+
 static bool sendTracepointFormat(const uint64_t currTime, Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) {
        if (!printb->printf(EVENTS_PATH "/%s/format", name)) {
-               logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::printf failed");
                return false;
        }
        if (!b->read(printb->getBuf())) {
-               logg->logMessage("%s(%s:%i): DynBuf::read failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::read failed");
                return false;
        }
-       buffer->format(currTime, b->getLength(), b->getBuf());
+       buffer->marshalFormat(currTime, b->getLength(), b->getBuf());
 
        return true;
 }
@@ -58,18 +60,18 @@ static void *syncFunc(void *arg)
        {
                sigset_t set;
                if (sigfillset(&set) != 0) {
-                       logg->logError(__FILE__, __LINE__, "sigfillset failed");
+                       logg->logError("sigfillset failed");
                        handleException();
                }
                if ((err = pthread_sigmask(SIG_SETMASK, &set, NULL)) != 0) {
-                       logg->logError(__FILE__, __LINE__, "pthread_sigmask failed");
+                       logg->logError("pthread_sigmask failed");
                        handleException();
                }
        }
 
        for (;;) {
                if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
-                       logg->logError(__FILE__, __LINE__, "clock_gettime failed");
+                       logg->logError("clock_gettime failed");
                        handleException();
                }
                const int64_t currTime = ts.tv_sec * NS_PER_S + ts.tv_nsec;
@@ -95,7 +97,7 @@ static void *syncFunc(void *arg)
 static long getMaxCoreNum() {
        DIR *dir = opendir("/sys/devices/system/cpu");
        if (dir == NULL) {
-               logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, opendir failed");
+               logg->logError("Unable to determine the number of cores on the target, opendir failed");
                handleException();
        }
 
@@ -114,22 +116,22 @@ static long getMaxCoreNum() {
        closedir(dir);
 
        if (maxCoreNum < 1) {
-               logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, no cpu# directories found");
+               logg->logError("Unable to determine the number of cores on the target, no cpu# directories found");
                handleException();
        }
 
        if (maxCoreNum >= NR_CPUS) {
-               logg->logError(__FILE__, __LINE__, "Too many cores on the target, please increase NR_CPUS in Config.h");
+               logg->logError("Too many cores on the target, please increase NR_CPUS in Config.h");
                handleException();
        }
 
        return maxCoreNum;
 }
 
-PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mIdleGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) {
+PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(NULL), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) {
        long l = sysconf(_SC_PAGE_SIZE);
        if (l < 0) {
-               logg->logError(__FILE__, __LINE__, "Unable to obtain the page size");
+               logg->logError("Unable to obtain the page size");
                handleException();
        }
        gSessionData->mPageSize = static_cast<int>(l);
@@ -137,15 +139,18 @@ PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAM
 }
 
 PerfSource::~PerfSource() {
+       delete mBuffer;
 }
 
 bool PerfSource::prepare() {
        DynBuf printb;
        DynBuf b1;
-       long long schedSwitchId;
        long long cpuIdleId;
 
-       const uint64_t currTime = getTime();
+       // MonotonicStarted has not yet been assigned!
+       const uint64_t currTime = 0;//getTime() - gSessionData->mMonotonicStarted;
+
+       mBuffer = new Buffer(0, FRAME_PERF_ATTRS, gSessionData->mTotalBufferSize*1024*1024, mSenderSem);
 
        // Reread cpuinfo since cores may have changed since startup
        gSessionData->readCpuInfo();
@@ -155,72 +160,59 @@ bool PerfSource::prepare() {
                        || !mUEvent.init()
                        || !mMonitor.add(mUEvent.getFd())
 
-                       || (schedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &printb)) < 0
-                       || !sendTracepointFormat(currTime, &mBuffer, SCHED_SWITCH, &printb, &b1)
+                       || !sendTracepointFormat(currTime, mBuffer, SCHED_SWITCH, &printb, &b1)
 
                        || (cpuIdleId = PerfDriver::getTracepointId(CPU_IDLE, &printb)) < 0
-                       || !sendTracepointFormat(currTime, &mBuffer, CPU_IDLE, &printb, &b1)
+                       || !sendTracepointFormat(currTime, mBuffer, CPU_IDLE, &printb, &b1)
 
-                       // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID
-                       || !mCountersGroup.add(currTime, &mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU)
-                       || !mIdleGroup.add(currTime, &mBuffer, 101/**/, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, PERF_GROUP_PER_CPU)
+                       || !sendTracepointFormat(currTime, mBuffer, CPU_FREQUENCY, &printb, &b1)
 
-                       // Only want TID and IP but not RAW on timer
-                       || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(currTime, &mBuffer, 102/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU))
+                       || !mCountersGroup.createCpuGroup(currTime, mBuffer)
+                       || !mCountersGroup.add(currTime, mBuffer, cpuIdleKey, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, PERF_GROUP_LEADER | PERF_GROUP_PER_CPU)
 
-                       || !gSessionData->perf.enable(currTime, &mCountersGroup, &mBuffer)
+                       || !gSessionData->perf.enable(currTime, &mCountersGroup, mBuffer)
                        || 0) {
-               logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("perf setup failed, are you running Linux 3.4 or later?");
                return false;
        }
 
        for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
                const int result = mCountersGroup.prepareCPU(cpu, &mMonitor);
                if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) {
-                       logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mCountersGroup failed");
-                       handleException();
-               }
-       }
-       for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
-               const int result = mIdleGroup.prepareCPU(cpu, &mMonitor);
-               if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) {
-                       logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mIdleGroup failed");
+                       logg->logError("PerfGroup::prepareCPU on mCountersGroup failed");
                        handleException();
                }
        }
 
        int numEvents = 0;
        for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
-               numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, &mBuffer);
-       }
-       for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
-               numEvents += mIdleGroup.onlineCPU(currTime, cpu, false, &mBuffer);
+               numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, mBuffer);
        }
        if (numEvents <= 0) {
-               logg->logMessage("%s(%s:%i): PerfGroup::onlineCPU failed on all cores", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("PerfGroup::onlineCPU failed on all cores");
                return false;
        }
 
        // Send the summary right before the start so that the monotonic delta is close to the start time
        if (!gSessionData->perf.summary(&mSummary)) {
-         logg->logError(__FILE__, __LINE__, "PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__);
-         handleException();
+               logg->logError("PerfDriver::summary failed");
+               handleException();
        }
 
        // Start the timer thread to used to sync perf and monotonic raw times
        pthread_t syncThread;
        if (pthread_create(&syncThread, NULL, syncFunc, NULL)) {
-         logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
-         handleException();
+               logg->logError("pthread_create failed");
+               handleException();
        }
        struct sched_param param;
        param.sched_priority = sched_get_priority_max(SCHED_FIFO);
        if (pthread_setschedparam(syncThread, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
-         logg->logError(__FILE__, __LINE__, "pthread_setschedparam failed");
-         handleException();
+               logg->logError("pthread_setschedparam failed");
+               handleException();
        }
 
-       mBuffer.commit(currTime);
+       mBuffer->commit(currTime);
 
        return true;
 }
@@ -240,18 +232,17 @@ void *procFunc(void *arg) {
 
        // Gator runs at a high priority, reset the priority to the default
        if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) {
-               logg->logError(__FILE__, __LINE__, "setpriority failed");
+               logg->logError("setpriority failed");
                handleException();
        }
 
        if (!readProcMaps(args->mCurrTime, args->mBuffer, &printb, &b)) {
-               logg->logError(__FILE__, __LINE__, "readProcMaps failed");
+               logg->logError("readProcMaps failed");
                handleException();
        }
-       args->mBuffer->commit(args->mCurrTime);
 
        if (!readKallsyms(args->mCurrTime, args->mBuffer, &args->mIsDone)) {
-               logg->logError(__FILE__, __LINE__, "readKallsyms failed");
+               logg->logError("readKallsyms failed");
                handleException();
        }
        args->mBuffer->commit(args->mCurrTime);
@@ -266,67 +257,72 @@ void PerfSource::run() {
        pthread_t procThread;
        ProcThreadArgs procThreadArgs;
 
+       if (pipe_cloexec(pipefd) != 0) {
+               logg->logError("pipe failed");
+               handleException();
+       }
+       mInterruptFd = pipefd[1];
+
+       if (!mMonitor.add(pipefd[0])) {
+               logg->logError("Monitor::add failed");
+               handleException();
+       }
+
        {
                DynBuf printb;
                DynBuf b1;
                DynBuf b2;
 
-               const uint64_t currTime = getTime();
+               const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted;
 
                // Start events before reading proc to avoid race conditions
-               if (!mCountersGroup.start() || !mIdleGroup.start()) {
-                       logg->logError(__FILE__, __LINE__, "PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__);
+               if (!mCountersGroup.start()) {
+                       logg->logError("PerfGroup::start failed");
                        handleException();
                }
 
-               if (!readProcComms(currTime, &mBuffer, &printb, &b1, &b2)) {
-                       logg->logError(__FILE__, __LINE__, "readProcComms failed");
+               mBuffer->perfCounterHeader(currTime);
+               for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+                       gSessionData->perf.read(mBuffer, cpu);
+               }
+               mBuffer->perfCounterFooter(currTime);
+
+               if (!readProcComms(currTime, mBuffer, &printb, &b1, &b2)) {
+                       logg->logError("readProcComms failed");
                        handleException();
                }
-               mBuffer.commit(currTime);
+               mBuffer->commit(currTime);
 
                // Postpone reading kallsyms as on android adb gets too backed up and data is lost
-               procThreadArgs.mBuffer = &mBuffer;
+               procThreadArgs.mBuffer = mBuffer;
                procThreadArgs.mCurrTime = currTime;
                procThreadArgs.mIsDone = false;
                if (pthread_create(&procThread, NULL, procFunc, &procThreadArgs)) {
-                       logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logError("pthread_create failed");
                        handleException();
                }
        }
 
-       if (pipe_cloexec(pipefd) != 0) {
-               logg->logError(__FILE__, __LINE__, "pipe failed");
-               handleException();
-       }
-       mInterruptFd = pipefd[1];
-
-       if (!mMonitor.add(pipefd[0])) {
-               logg->logError(__FILE__, __LINE__, "Monitor::add failed");
-               handleException();
-       }
-
-       int timeout = -1;
-       if (gSessionData->mLiveRate > 0) {
-               timeout = gSessionData->mLiveRate/NS_PER_MS;
-       }
-
        sem_post(mStartProfile);
 
+       const uint64_t NO_RATE = ~0ULL;
+       const uint64_t rate = gSessionData->mLiveRate > 0 && gSessionData->mSampleRate > 0 ? gSessionData->mLiveRate : NO_RATE;
+       uint64_t nextTime = 0;
+       int timeout = rate != NO_RATE ? 0 : -1;
        while (gSessionData->mSessionIsActive) {
                // +1 for uevents, +1 for pipe
                struct epoll_event events[NR_CPUS + 2];
                int ready = mMonitor.wait(events, ARRAY_LENGTH(events), timeout);
                if (ready < 0) {
-                       logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
+                       logg->logError("Monitor::wait failed");
                        handleException();
                }
-               const uint64_t currTime = getTime();
+               const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted;
 
                for (int i = 0; i < ready; ++i) {
                        if (events[i].data.fd == mUEvent.getFd()) {
                                if (!handleUEvent(currTime)) {
-                                       logg->logError(__FILE__, __LINE__, "PerfSource::handleUEvent failed");
+                                       logg->logError("PerfSource::handleUEvent failed");
                                        handleException();
                                }
                                break;
@@ -337,18 +333,24 @@ void PerfSource::run() {
                sem_post(mSenderSem);
 
                // In one shot mode, stop collection once all the buffers are filled
-               // Assume timeout == 0 in this case
-               if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
-                       logg->logMessage("%s(%s:%i): One shot", __FUNCTION__, __FILE__, __LINE__);
+               if (gSessionData->mOneShot && gSessionData->mSessionIsActive && ((mSummary.bytesAvailable() <= 0) || (mBuffer->bytesAvailable() <= 0) || mCountersBuf.isFull())) {
+                       logg->logMessage("One shot (perf)");
                        child->endSession();
                }
+
+               if (rate != NO_RATE) {
+                       while (currTime > nextTime) {
+                               nextTime += rate;
+                       }
+                       // + NS_PER_MS - 1 to ensure always rounding up
+                       timeout = max(0, (int)((nextTime + NS_PER_MS - 1 - getTime() + gSessionData->mMonotonicStarted)/NS_PER_MS));
+               }
        }
 
        procThreadArgs.mIsDone = true;
        pthread_join(procThread, NULL);
-       mIdleGroup.stop();
        mCountersGroup.stop();
-       mBuffer.setDone();
+       mBuffer->setDone();
        mIsDone = true;
 
        // send a notification that data is ready
@@ -362,57 +364,53 @@ void PerfSource::run() {
 bool PerfSource::handleUEvent(const uint64_t currTime) {
        UEventResult result;
        if (!mUEvent.read(&result)) {
-               logg->logMessage("%s(%s:%i): UEvent::Read failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("UEvent::Read failed");
                return false;
        }
 
        if (strcmp(result.mSubsystem, "cpu") == 0) {
                if (strncmp(result.mDevPath, CPU_DEVPATH, sizeof(CPU_DEVPATH) - 1) != 0) {
-                       logg->logMessage("%s(%s:%i): Unexpected cpu DEVPATH format", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("Unexpected cpu DEVPATH format");
                        return false;
                }
                char *endptr;
                errno = 0;
                int cpu = strtol(result.mDevPath + sizeof(CPU_DEVPATH) - 1, &endptr, 10);
                if (errno != 0 || *endptr != '\0') {
-                       logg->logMessage("%s(%s:%i): strtol failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("strtol failed");
                        return false;
                }
 
                if (cpu >= gSessionData->mCores) {
-                       logg->logError(__FILE__, __LINE__, "Only %i cores are expected but core %i reports %s", gSessionData->mCores, cpu, result.mAction);
+                       logg->logError("Only %i cores are expected but core %i reports %s", gSessionData->mCores, cpu, result.mAction);
                        handleException();
                }
 
                if (strcmp(result.mAction, "online") == 0) {
-                       mBuffer.onlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu);
+                       mBuffer->onlineCPU(currTime, cpu);
                        // Only call onlineCPU if prepareCPU succeeded
-                       bool result = false;
+                       bool ret = false;
                        int err = mCountersGroup.prepareCPU(cpu, &mMonitor);
                        if (err == PG_CPU_OFFLINE) {
-                               result = true;
+                               ret = true;
                        } else if (err == PG_SUCCESS) {
-                               if (mCountersGroup.onlineCPU(currTime, cpu, true, &mBuffer)) {
-                                       err = mIdleGroup.prepareCPU(cpu, &mMonitor);
-                                       if (err == PG_CPU_OFFLINE) {
-                                               result = true;
-                                       } else if (err == PG_SUCCESS) {
-                                               if (mIdleGroup.onlineCPU(currTime, cpu, true, &mBuffer)) {
-                                                       result = true;
-                                               }
-                                       }
+                               if (mCountersGroup.onlineCPU(currTime, cpu, true, mBuffer) > 0) {
+                                       mBuffer->perfCounterHeader(currTime);
+                                       gSessionData->perf.read(mBuffer, cpu);
+                                       mBuffer->perfCounterFooter(currTime);
+                                       ret = true;
                                }
                        }
-                       mBuffer.commit(currTime);
+                       mBuffer->commit(currTime);
 
                        gSessionData->readCpuInfo();
                        gSessionData->perf.coreName(currTime, &mSummary, cpu);
                        mSummary.commit(currTime);
-                       return result;
+                       return ret;
                } else if (strcmp(result.mAction, "offline") == 0) {
-                       const bool result = mCountersGroup.offlineCPU(cpu) && mIdleGroup.offlineCPU(cpu);
-                       mBuffer.offlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu);
-                       return result;
+                       const bool ret = mCountersGroup.offlineCPU(cpu);
+                       mBuffer->offlineCPU(currTime, cpu);
+                       return ret;
                }
        }
 
@@ -424,14 +422,14 @@ void PerfSource::interrupt() {
                int8_t c = 0;
                // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread
                if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) {
-                       logg->logError(__FILE__, __LINE__, "write failed");
+                       logg->logError("write failed");
                        handleException();
                }
        }
 }
 
 bool PerfSource::isDone () {
-       return mBuffer.isDone() && mIsDone && mCountersBuf.isEmpty();
+       return mBuffer->isDone() && mIsDone && mCountersBuf.isEmpty();
 }
 
 void PerfSource::write (Sender *sender) {
@@ -439,11 +437,11 @@ void PerfSource::write (Sender *sender) {
                mSummary.write(sender);
                gSessionData->mSentSummary = true;
        }
-       if (!mBuffer.isDone()) {
-               mBuffer.write(sender);
+       if (!mBuffer->isDone()) {
+               mBuffer->write(sender);
        }
        if (!mCountersBuf.send(sender)) {
-               logg->logError(__FILE__, __LINE__, "PerfBuffer::send failed");
+               logg->logError("PerfBuffer::send failed");
                handleException();
        }
 }
index ce1eafe8e9532091ebcfb6fc6e65d06baae36b22..feec1c26992247ca86d05c527c5841d0790c21f1 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -36,10 +36,9 @@ private:
        bool handleUEvent(const uint64_t currTime);
 
        Buffer mSummary;
-       Buffer mBuffer;
+       Buffer *mBuffer;
        PerfBuffer mCountersBuf;
        PerfGroup mCountersGroup;
-       PerfGroup mIdleGroup;
        Monitor mMonitor;
        UEvent mUEvent;
        sem_t *const mSenderSem;
index e6b26b1199fa9d997f16a5305871e5515caf7bc9..4ba59b632836f2b508f1bf66c30482404d84a355 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -31,20 +31,20 @@ struct ProcStat {
 
 static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf *const b) {
        if (!b->read(pathname)) {
-               logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::read failed, likely because the thread exited");
                // This is not a fatal error - the thread just doesn't exist any more
                return true;
        }
 
        char *comm = strchr(b->getBuf(), '(');
        if (comm == NULL) {
-               logg->logMessage("%s(%s:%i): parsing stat failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("parsing stat failed");
                return false;
        }
        ++comm;
        char *const str = strrchr(comm, ')');
        if (str == NULL) {
-               logg->logMessage("%s(%s:%i): parsing stat failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("parsing stat failed");
                return false;
        }
        *str = '\0';
@@ -53,7 +53,7 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf
 
        const int count = sscanf(str + 2, " %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %ld", &ps->numThreads);
        if (count != 1) {
-               logg->logMessage("%s(%s:%i): sscanf failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("sscanf failed");
                return false;
        }
 
@@ -65,7 +65,7 @@ static const char APP_PROCESS[] = "app_process";
 static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) {
        if (tid == -1 ? !printb->printf("/proc/%i/exe", pid)
                        : !printb->printf("/proc/%i/task/%i/exe", pid, tid)) {
-               logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::printf failed");
                return NULL;
        }
 
@@ -82,7 +82,7 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
                // readlink /proc/[pid]/exe returns ENOENT for kernel threads
                image = "\0";
        } else {
-               logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::readlink failed");
                return NULL;
        }
 
@@ -94,12 +94,12 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
 
        if (tid == -1 ? !printb->printf("/proc/%i/cmdline", pid)
                        : !printb->printf("/proc/%i/task/%i/cmdline", pid, tid)) {
-               logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::printf failed");
                return NULL;
        }
 
        if (!b->read(printb->getBuf())) {
-               logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::read failed, likely because the thread exited");
                return NULL;
        }
 
@@ -110,12 +110,12 @@ static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const in
        bool result = false;
 
        if (!b1->printf("/proc/%i/task", pid)) {
-               logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("DynBuf::printf failed");
                return result;
        }
        DIR *task = opendir(b1->getBuf());
        if (task == NULL) {
-               logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("opendir failed");
                // This is not a fatal error - the thread just doesn't exist any more
                return true;
        }
@@ -130,22 +130,22 @@ static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const in
                }
 
                if (!printb->printf("/proc/%i/task/%i/stat", pid, tid)) {
-                       logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("DynBuf::printf failed");
                        goto fail;
                }
                ProcStat ps;
                if (!readProcStat(&ps, printb->getBuf(), b1)) {
-                       logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("readProcStat failed");
                        goto fail;
                }
 
                const char *const image = readProcExe(printb, pid, tid, b2);
                if (image == NULL) {
-                       logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("readImage failed");
                        goto fail;
                }
 
-               buffer->comm(currTime, pid, tid, image, ps.comm);
+               buffer->marshalComm(currTime, pid, tid, image, ps.comm);
        }
 
        result = true;
@@ -161,7 +161,7 @@ bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const
 
        DIR *proc = opendir("/proc");
        if (proc == NULL) {
-               logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("opendir failed");
                return result;
        }
 
@@ -175,26 +175,26 @@ bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const
                }
 
                if (!printb->printf("/proc/%i/stat", pid)) {
-                       logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("DynBuf::printf failed");
                        goto fail;
                }
                ProcStat ps;
                if (!readProcStat(&ps, printb->getBuf(), b1)) {
-                       logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("readProcStat failed");
                        goto fail;
                }
 
                if (ps.numThreads <= 1) {
                        const char *const image = readProcExe(printb, pid, -1, b1);
                        if (image == NULL) {
-                               logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__);
+                               logg->logMessage("readImage failed");
                                goto fail;
                        }
 
-                       buffer->comm(currTime, pid, pid, image, ps.comm);
+                       buffer->marshalComm(currTime, pid, pid, image, ps.comm);
                } else {
                        if (!readProcTask(currTime, buffer, pid, printb, b1, b2)) {
-                               logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__);
+                               logg->logMessage("readProcTask failed");
                                goto fail;
                        }
                }
@@ -213,7 +213,7 @@ bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const p
 
        DIR *proc = opendir("/proc");
        if (proc == NULL) {
-               logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("opendir failed");
                return result;
        }
 
@@ -227,16 +227,16 @@ bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const p
                }
 
                if (!printb->printf("/proc/%i/maps", pid)) {
-                       logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("DynBuf::printf failed");
                        goto fail;
                }
                if (!b->read(printb->getBuf())) {
-                       logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
+                       logg->logMessage("DynBuf::read failed, likely because the process exited");
                        // This is not a fatal error - the process just doesn't exist any more
                        continue;
                }
 
-               buffer->maps(currTime, pid, pid, b->getBuf());
+               buffer->marshalMaps(currTime, pid, pid, b->getBuf());
        }
 
        result = true;
@@ -251,7 +251,7 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con
        int fd = ::open("/proc/kallsyms", O_RDONLY | O_CLOEXEC);
 
        if (fd < 0) {
-               logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("open failed");
                return true;
        };
 
@@ -260,7 +260,7 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con
        while (gSessionData->mSessionIsActive && !ACCESS_ONCE(*isDone)) {
                // Assert there is still space in the buffer
                if (sizeof(buf) - pos - 1 == 0) {
-                       logg->logError(__FILE__, __LINE__, "no space left in buffer");
+                       logg->logError("no space left in buffer");
                        handleException();
                }
 
@@ -268,13 +268,13 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con
                        // -1 to reserve space for \0
                        const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
                        if (bytes < 0) {
-                               logg->logError(__FILE__, __LINE__, "read failed", __FUNCTION__, __FILE__, __LINE__);
+                               logg->logError("read failed");
                                handleException();
                        }
                        if (bytes == 0) {
                                // Assert the buffer is empty
                                if (pos != 0) {
-                                       logg->logError(__FILE__, __LINE__, "buffer not empty on eof");
+                                       logg->logError("buffer not empty on eof");
                                        handleException();
                                }
                                break;
@@ -288,13 +288,13 @@ bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *con
                        if (buf[newline] == '\n') {
                                const char was = buf[newline + 1];
                                buf[newline + 1] = '\0';
-                               buffer->kallsyms(currTime, buf);
+                               buffer->marshalKallsyms(currTime, buf);
                                // Sleep 3 ms to avoid sending out too much data too quickly
                                usleep(3000);
                                buf[0] = was;
                                // Assert the memory regions do not overlap
                                if (pos - newline >= newline + 1) {
-                                       logg->logError(__FILE__, __LINE__, "memcpy src and dst overlap");
+                                       logg->logError("memcpy src and dst overlap");
                                        handleException();
                                }
                                if (pos - newline - 2 > 0) {
index 2a1a7cbc1e9981829c323e1a7208b201ae8182f2..fcc48c546d0544d462f59dc73484db889ee5bb74 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 8a54a6678974a76b9b3991c3924793301dead028..d7ad757165a2923a3970f0e989f59096b797115f 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -30,7 +30,7 @@ Sender::Sender(OlySocket* socket) {
                // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+
                while (strcmp("STREAMLINE", streamline) != 0) {
                        if (mDataSocket->receiveString(streamline, sizeof(streamline)) == -1) {
-                               logg->logError(__FILE__, __LINE__, "Socket disconnected");
+                               logg->logError("Socket disconnected");
                                handleException();
                        }
                }
@@ -67,7 +67,7 @@ void Sender::createDataFile(char* apcDir) {
        sprintf(mDataFileName, "%s/0000000000", apcDir);
        mDataFile = fopen_cloexec(mDataFileName, "wb");
        if (!mDataFile) {
-               logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", mDataFileName);
+               logg->logError("Failed to open binary file: %s", mDataFileName);
                handleException();
        }
 }
@@ -120,7 +120,7 @@ void Sender::writeData(const char* data, int length, int type) {
                logg->logMessage("Writing data with length %d", length);
                // Send data to the data file
                if (fwrite(data, 1, length, mDataFile) != (unsigned int)length) {
-                       logg->logError(__FILE__, __LINE__, "Failed writing binary file %s", mDataFileName);
+                       logg->logError("Failed writing binary file %s", mDataFileName);
                        handleException();
                }
        }
index 5aa911713820cf347901715430e39b8e0cf01806..8f542026e90d97540e5cc221a275ca5c083db0bc 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 0e65d7842647d95c48cc1f5950ed550a4a368062..2b661bdf294c59ead6585fd892971d6d5d5b8669 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -13,7 +13,6 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
-#include "CPUFreqDriver.h"
 #include "DiskIODriver.h"
 #include "FSDriver.h"
 #include "HwmonDriver.h"
@@ -31,8 +30,7 @@ SessionData::SessionData() {
        usDrivers[1] = new FSDriver();
        usDrivers[2] = new MemInfoDriver();
        usDrivers[3] = new NetDriver();
-       usDrivers[4] = new CPUFreqDriver();
-       usDrivers[5] = new DiskIODriver();
+       usDrivers[4] = new DiskIODriver();
        initialize();
 }
 
@@ -50,7 +48,7 @@ void SessionData::initialize() {
        // Share mCpuIds across all instances of gatord
        mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        if (mCpuIds == MAP_FAILED) {
-               logg->logError(__FILE__, __LINE__, "Unable to mmap shared memory for cpuids");
+               logg->logError("Unable to mmap shared memory for cpuids");
                handleException();
        }
        memset(mCpuIds, -1, cpuIdSize);
@@ -61,6 +59,7 @@ void SessionData::initialize() {
        mConfigurationXMLPath = NULL;
        mSessionXMLPath = NULL;
        mEventsXMLPath = NULL;
+       mEventsXMLAppend = NULL;
        mTargetPath = NULL;
        mAPCDir = NULL;
        mCaptureWorkingDir = NULL;
@@ -75,6 +74,7 @@ void SessionData::initialize() {
        // sysconf(_SC_NPROCESSORS_CONF) is unreliable on 2.6 Android, get the value from the kernel module
        mCores = 1;
        mPageSize = 0;
+       mAnnotateStart = -1;
 }
 
 void SessionData::parseSessionXML(char* xmlString) {
@@ -91,7 +91,7 @@ void SessionData::parseSessionXML(char* xmlString) {
        } else if (strcmp(session.parameters.sample_rate, "none") == 0) {
                mSampleRate = 0;
        } else {
-               logg->logError(__FILE__, __LINE__, "Invalid sample rate (%s) in session xml.", session.parameters.sample_rate);
+               logg->logError("Invalid sample rate (%s) in session xml.", session.parameters.sample_rate);
                handleException();
        }
        mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
@@ -108,7 +108,7 @@ void SessionData::parseSessionXML(char* xmlString) {
        } else if (strcmp(session.parameters.buffer_mode, "large") == 0) {
                mTotalBufferSize = 16;
        } else {
-               logg->logError(__FILE__, __LINE__, "Invalid value for buffer mode in session xml.");
+               logg->logError("Invalid value for buffer mode in session xml.");
                handleException();
        }
 
@@ -120,7 +120,7 @@ void SessionData::parseSessionXML(char* xmlString) {
        }
 
        if (!mAllowCommands && (mCaptureCommand != NULL)) {
-               logg->logError(__FILE__, __LINE__, "Running a command during a capture is not currently allowed. Please restart gatord with the -a flag.");
+               logg->logError("Running a command during a capture is not currently allowed. Please restart gatord with the -a flag.");
                handleException();
        }
 }
@@ -139,6 +139,20 @@ void SessionData::readModel() {
        fclose(fh);
 }
 
+static void setImplementer(int &cpuId, const int implementer) {
+       if (cpuId == -1) {
+               cpuId = 0;
+       }
+       cpuId |= implementer << 12;
+}
+
+static void setPart(int &cpuId, const int part) {
+       if (cpuId == -1) {
+               cpuId = 0;
+       }
+       cpuId |= part;
+}
+
 void SessionData::readCpuInfo() {
        char temp[256]; // arbitrarily large amount
        mMaxCpuId = -1;
@@ -150,7 +164,7 @@ void SessionData::readCpuInfo() {
                return;
        }
 
-       bool foundCoreName = false;
+       bool foundCoreName = (strcmp(mCoreName, CORE_NAME_UNKNOWN) != 0);
        int processor = -1;
        while (fgets(temp, sizeof(temp), f)) {
                const size_t len = strlen(temp);
@@ -166,10 +180,11 @@ void SessionData::readCpuInfo() {
                        temp[len - 1] = '\0';
                }
 
-               const bool foundHardware = strstr(temp, "Hardware") != 0;
+               const bool foundHardware = !foundCoreName && strstr(temp, "Hardware") != 0;
+               const bool foundCPUImplementer = strstr(temp, "CPU implementer") != 0;
                const bool foundCPUPart = strstr(temp, "CPU part") != 0;
                const bool foundProcessor = strstr(temp, "processor") != 0;
-               if (foundHardware || foundCPUPart || foundProcessor) {
+               if (foundHardware || foundCPUImplementer || foundCPUPart || foundProcessor) {
                        char* position = strchr(temp, ':');
                        if (position == NULL || (unsigned int)(position - temp) + 2 >= strlen(temp)) {
                                logg->logMessage("Unknown format of /proc/cpuinfo\n"
@@ -178,22 +193,31 @@ void SessionData::readCpuInfo() {
                        }
                        position += 2;
 
-                       if (foundHardware && (strcmp(mCoreName, CORE_NAME_UNKNOWN) == 0)) {
+                       if (foundHardware) {
                                strncpy(mCoreName, position, sizeof(mCoreName));
                                mCoreName[sizeof(mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
                                foundCoreName = true;
                        }
 
+                       if (foundCPUImplementer) {
+                               const int implementer = strtol(position, NULL, 0);
+                               if (processor >= NR_CPUS) {
+                                       logg->logMessage("Too many processors, please increase NR_CPUS");
+                               } else if (processor >= 0) {
+                                       setImplementer(mCpuIds[processor], implementer);
+                               } else {
+                                       setImplementer(mMaxCpuId, implementer);
+                               }
+                       }
+
                        if (foundCPUPart) {
                                const int cpuId = strtol(position, NULL, 0);
-                               // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId
-                               if (cpuId > mMaxCpuId) {
-                                       mMaxCpuId = cpuId;
-                               }
                                if (processor >= NR_CPUS) {
                                        logg->logMessage("Too many processors, please increase NR_CPUS");
                                } else if (processor >= 0) {
-                                       mCpuIds[processor] = cpuId;
+                                       setPart(mCpuIds[processor], cpuId);
+                               } else {
+                                       setPart(mMaxCpuId, cpuId);
                                }
                        }
 
@@ -203,6 +227,13 @@ void SessionData::readCpuInfo() {
                }
        }
 
+       // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId
+       for (int i = 0; i < NR_CPUS; ++i) {
+               if (mCpuIds[i] > mMaxCpuId) {
+                       mMaxCpuId = mCpuIds[i];
+               }
+       }
+
        if (!foundCoreName) {
                logg->logMessage("Could not determine core name from /proc/cpuinfo\n"
                                 "The core name in the captured xml file will be 'unknown'.");
@@ -213,7 +244,7 @@ void SessionData::readCpuInfo() {
 uint64_t getTime() {
        struct timespec ts;
        if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
-               logg->logError(__FILE__, __LINE__, "Failed to get uptime");
+               logg->logError("Failed to get uptime");
                handleException();
        }
        return (NS_PER_S*ts.tv_sec + ts.tv_nsec);
index ed282af4a869d9b34913dfec4f6fa61c095d3eec..d0c8900317a54a5bea34d43139896a04ab613aa5 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,7 +11,6 @@
 
 #include <stdint.h>
 
-#include "AnnotateListener.h"
 #include "Config.h"
 #include "Counter.h"
 #include "FtraceDriver.h"
@@ -19,7 +18,7 @@
 #include "MaliVideoDriver.h"
 #include "PerfDriver.h"
 
-#define PROTOCOL_VERSION 20
+#define PROTOCOL_VERSION 21
 // Differentiates development versions (timestamp) from release versions
 #define PROTOCOL_DEV 1000
 
@@ -43,18 +42,18 @@ public:
        void readModel();
        void readCpuInfo();
 
-       PolledDriver *usDrivers[6];
+       PolledDriver *usDrivers[5];
        KMod kmod;
        PerfDriver perf;
        MaliVideoDriver maliVideo;
        FtraceDriver ftraceDriver;
-       AnnotateListener annotateListener;
 
        char mCoreName[MAX_STRING_LEN];
        struct ImageLinkList *mImages;
        char *mConfigurationXMLPath;
        char *mSessionXMLPath;
        char *mEventsXMLPath;
+       char *mEventsXMLAppend;
        char *mTargetPath;
        char *mAPCDir;
        char *mCaptureWorkingDir;
@@ -81,6 +80,7 @@ public:
        int mPageSize;
        int *mCpuIds;
        int mMaxCpuId;
+       int mAnnotateStart;
 
        // PMU Counters
        int mCounterOverflow;
@@ -93,6 +93,7 @@ private:
 };
 
 extern SessionData* gSessionData;
+extern const char *const gSrcMd5;
 
 uint64_t getTime();
 int getEventKey();
index dea4c8f299ecc1d8661654b41153b67533a74fae..c638dea4591226f4a9b67fd484498ce32b4c3c45 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -36,7 +36,7 @@ SessionXML::SessionXML(const char *str) {
        parameters.call_stack_unwinding = false;
        parameters.live_rate = 0;
        mSessionXML = str;
-       logg->logMessage(mSessionXML);
+       logg->logMessage("%s", mSessionXML);
 }
 
 SessionXML::~SessionXML() {
@@ -55,7 +55,7 @@ void SessionXML::parse() {
                return;
        }
 
-       logg->logError(__FILE__, __LINE__, "No session tag found in the session.xml file");
+       logg->logError("No session tag found in the session.xml file");
        handleException();
 }
 
@@ -63,7 +63,7 @@ void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) {
        int version = 0;
        if (mxmlElementGetAttr(node, ATTR_VERSION)) version = strtol(mxmlElementGetAttr(node, ATTR_VERSION), NULL, 10);
        if (version != 1) {
-               logg->logError(__FILE__, __LINE__, "Invalid session.xml version: %d", version);
+               logg->logError("Invalid session.xml version: %d", version);
                handleException();
        }
 
index 53965749c74b054005e7cee0ff17676aeb8696ba..2ba276a380213e9484d9e407b43f81b247e5a46a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index d4ce0328c6330005af5dafc0f71b74f124f7105a..7dd83ceafcce07c8f9057e7445f483fabe3e6e61 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -15,7 +15,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/utsname.h>
 #include <sys/wait.h>
 #include "Config.h"
 #include "DynBuf.h"
 #include "Logging.h"
+#include "SessionData.h"
+
+#define GATOR_MSG "gator: "
+#define GATOR_ERROR "gator: error: "
+#define GATOR_CONFIRM "gator: confirm: "
 
 bool getLinuxVersion(int version[3]) {
        // Check the kernel version
        struct utsname utsname;
        if (uname(&utsname) != 0) {
-               logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("uname failed");
                return false;
        }
 
@@ -57,7 +64,7 @@ static int pgrep_gator(DynBuf *const printb) {
 
        DIR *proc = opendir("/proc");
        if (proc == NULL) {
-               logg->logError(__FILE__, __LINE__, "gator: error: opendir failed");
+               logg->logError(GATOR_ERROR "opendir failed");
                handleException();
        }
 
@@ -73,7 +80,7 @@ static int pgrep_gator(DynBuf *const printb) {
                }
 
                if (!printb->printf("/proc/%i/stat", pid)) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: DynBuf::printf failed");
+                       logg->logError(GATOR_ERROR "DynBuf::printf failed");
                        handleException();
                }
 
@@ -84,21 +91,35 @@ static int pgrep_gator(DynBuf *const printb) {
 
                char *comm = strchr(b.getBuf(), '(');
                if (comm == NULL) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: parsing stat begin failed");
+                       logg->logError(GATOR_ERROR "parsing stat comm begin failed");
                        handleException();
                }
                ++comm;
                char *const str = strrchr(comm, ')');
                if (str == NULL) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: parsing stat end failed");
+                       logg->logError(GATOR_ERROR "parsing stat comm end failed");
                        handleException();
                }
                *str = '\0';
 
-               if (strncmp(comm, "gator", 5) == 0) {
-                       // Assume there is only one gator process
-                       return pid;
+               if (strncmp(comm, "gator", 5) != 0) {
+                       continue;
+               }
+
+               char state;
+               const int count = sscanf(str + 2, " %c ", &state);
+               if (count != 1) {
+                       logg->logError(GATOR_ERROR "parsing stat state failed");
+                       handleException();
+               }
+
+               if (state == 'Z') {
+                       // This gator is a zombie, ignore
+                       continue;
                }
+
+               // Assume there is only one gator process
+               return pid;
        }
 
        closedir(proc);
@@ -106,73 +127,106 @@ static int pgrep_gator(DynBuf *const printb) {
        return -1;
 }
 
-int update(const char *const gatorPath) {
-       printf("gator: starting\n");
+static bool confirm(const char *const message) {
+       char buf[1<<10];
+
+       printf(GATOR_CONFIRM "%s\n", message);
+       while (fgets(buf, sizeof(buf), stdin) != NULL) {
+               if (strcmp(buf, "y\n") == 0) {
+                       return true;
+               }
+               if (strcmp(buf, "n\n") == 0) {
+                       return false;
+               }
+               // Ignore unrecognized input
+       }
+
+       return false;
+}
+
+void update(const char *const gatorPath) {
+       printf(GATOR_MSG "starting\n");
 
        int version[3];
        if (!getLinuxVersion(version)) {
-               logg->logError(__FILE__, __LINE__, "gator: error: getLinuxVersion failed");
+               logg->logError(GATOR_ERROR "getLinuxVersion failed");
                handleException();
        }
 
        if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(2, 6, 32)) {
-               logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as this kernel version is not supported. Please upgrade the kernel on your device.");
+               logg->logError(GATOR_ERROR "Streamline can't automatically setup gator as this kernel version is not supported. Please upgrade the kernel on your device.");
                handleException();
        }
 
        if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(3, 4, 0)) {
-               logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as gator.ko is required for this version of Linux. Please build gator.ko and gatord and install them on your device.");
-               handleException();
-       }
-
-       if (access("/sys/module/gator", F_OK) == 0) {
-               logg->logError(__FILE__, __LINE__, "gator: error: Streamline has detected that the gator kernel module is loaded on your device. Please build an updated version of gator.ko and gatord and install them on your device.");
+               logg->logError(GATOR_ERROR "Streamline can't automatically setup gator as gator.ko is required for this version of Linux. Please build gator.ko and gatord and install them on your device.");
                handleException();
        }
 
        if (geteuid() != 0) {
-               printf("gator: trying sudo\n");
+               printf(GATOR_MSG "trying sudo\n");
                execlp("sudo", "sudo", gatorPath, "-u", NULL);
                // Streamline will provide the password if needed
 
-               printf("gator: trying su\n");
+               printf(GATOR_MSG "trying su\n");
                char buf[1<<10];
-               snprintf(buf, sizeof(buf), "%s -u", gatorPath);
-               execlp("su", "su", "-", "-c", buf, NULL);
+               /*
+                * Different versions of su handle additional -c command line options differently and expect the
+                * arguments in different ways. Try both ways wrapped in a shell.
+                *
+                * Then invoke another shell after su as it avoids odd failures on some Android systems
+                */
+               snprintf(buf, sizeof(buf), "su -c \"sh -c '%s -u'\" || su -c sh -c '%s -u'", gatorPath, gatorPath);
+               execlp("sh", "sh", "-c", buf, NULL);
                // Streamline will provide the password if needed
 
-               logg->logError(__FILE__, __LINE__, "gator: error: Streamline was unable to sudo to root on your device. Please double check passwords, ensure sudo or su work with this user or try a different username.");
+               logg->logError(GATOR_ERROR "Streamline was unable to sudo to root on your device. Please double check passwords, ensure sudo or su work with this user or try a different username.");
                handleException();
        }
-       printf("gator: now root\n");
+       printf(GATOR_MSG "now root\n");
+
+       if (access("/sys/module/gator", F_OK) == 0) {
+               if (!confirm("Streamline has detected that the gator kernel module is loaded on your device. Click yes to switch to user space gator, click no to abort the install.")) {
+                       printf("gator: cancel\n");
+                       exit(-1);
+               }
+       }
 
        // setenforce 0 not needed for userspace gator
 
        // Kill existing gator
-       DynBuf gatorStatPath;
-       int gator_main = pgrep_gator(&gatorStatPath);
+       DynBuf printb;
+       int gator_main = pgrep_gator(&printb);
        if (gator_main > 0) {
                if (kill(gator_main, SIGTERM) != 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: kill SIGTERM failed");
+                       logg->logError(GATOR_ERROR "kill SIGTERM failed");
+                       handleException();
+               }
+               if (!printb.printf("/proc/%i/exe", gator_main)) {
+                       logg->logError(GATOR_ERROR "DynBuf::printf failed");
                        handleException();
                }
                for (int i = 0; ; ++i) {
-                       if (access(gatorStatPath.getBuf(), F_OK) != 0) {
+                       // /proc/<pid>/exe exists but will not be accessible for zombies
+                       if (access(printb.getBuf(), F_OK) != 0) {
                                break;
                        }
                        if (i == 5) {
                                if (kill(gator_main, SIGKILL) != 0) {
-                                       logg->logError(__FILE__, __LINE__, "gator: error: kill SIGKILL failed");
+                                       logg->logError(GATOR_ERROR "kill SIGKILL failed");
                                        handleException();
                                }
                        } else if (i >= 10) {
-                               logg->logError(__FILE__, __LINE__, "gator: error: unable to kill running gator");
+                               logg->logError(GATOR_ERROR "unable to kill running gator");
                                handleException();
                        }
                        sleep(1);
                }
        }
-       printf("gator: no gatord running\n");
+       printf(GATOR_MSG "no gatord running\n");
+
+       umount("/dev/gator");
+       syscall(__NR_delete_module, "gator", O_NONBLOCK);
 
        rename("gatord", "gatord.old");
        rename("gator.ko", "gator.ko.old");
@@ -183,50 +237,88 @@ int update(const char *const gatorPath) {
        if (dot != NULL) {
                *dot = '\0';
                if (rename(gatorPath, newGatorPath) != 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: rename failed");
+                       logg->logError(GATOR_ERROR "rename failed");
                        handleException();
                }
        }
 
-       // Fork and start gatord (redirect stdout and stderr)
+       char buf[128];
+       int pipefd[2];
+       if (pipe_cloexec(pipefd) != 0) {
+               logg->logError(GATOR_ERROR "pipe failed");
+               handleException();
+       }
+
+       // Fork and start gatord (redirect stdin, stdout and stderr so shell can close)
        int child = fork();
        if (child < 0) {
-               logg->logError(__FILE__, __LINE__, "gator: error: fork failed");
+               logg->logError(GATOR_ERROR "fork failed");
                handleException();
        } else if (child == 0) {
-               int inFd = open("/dev/null", O_RDONLY | O_CLOEXEC);
+               int inFd;
+               int outFd;
+               int errFd;
+               int result = -1;
+
+               buf[0] = '\0';
+               close(pipefd[0]);
+
+               inFd = open("/dev/null", O_RDONLY | O_CLOEXEC);
                if (inFd < 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: open of /dev/null failed");
-                       handleException();
+                       snprintf(buf, sizeof(buf), GATOR_ERROR "open of /dev/null failed");
+                       goto fail_exit;
                }
-               int outFd = open("gatord.out", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
+               outFd = open("gatord.out", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
                if (outFd < 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.out failed");
-                       handleException();
+                       snprintf(buf, sizeof(buf), GATOR_ERROR "open of gatord.out failed");
+                       goto fail_exit;
                }
-               int errFd = open("gatord.err", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
+               errFd = open("gatord.err", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
                if (errFd < 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.err failed");
-                       handleException();
+                       snprintf(buf, sizeof(buf), GATOR_ERROR "open of gatord.err failed");
+                       goto fail_exit;
                }
                if (dup2(inFd, STDIN_FILENO) < 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdin failed");
-                       handleException();
+                       snprintf(buf, sizeof(buf), GATOR_ERROR "dup2 for stdin failed");
+                       goto fail_exit;
                }
+               fflush(stdout);
                if (dup2(outFd, STDOUT_FILENO) < 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdout failed");
-                       handleException();
+                       snprintf(buf, sizeof(buf), GATOR_ERROR "dup2 for stdout failed");
+                       goto fail_exit;
                }
+               fflush(stderr);
                if (dup2(errFd, STDERR_FILENO) < 0) {
-                       logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stderr failed");
-                       handleException();
+                       snprintf(buf, sizeof(buf), GATOR_ERROR "dup2 for stderr failed");
+                       goto fail_exit;
                }
-               execlp(newGatorPath, newGatorPath, "-a", NULL);
-               logg->logError(__FILE__, __LINE__, "gator: error: execlp failed");
-               handleException();
+
+               snprintf(buf, sizeof(buf), GATOR_MSG "done");
+               result = 0;
+
+       fail_exit:
+               if (buf[0] != '\0') {
+                       const ssize_t bytes = write(pipefd[1], buf, sizeof(buf));
+                       // Can't do anything if this fails
+                       (void)bytes;
+               }
+               close(pipefd[1]);
+
+               if (result == 0) {
+                       // Continue to execute gator normally
+                       return;
+               }
+               exit(-1);
        }
 
-       printf("gator: done\n");
+       close(pipefd[1]);
+       const ssize_t bytes = read(pipefd[0], buf, sizeof(buf));
+       if (bytes > 0) {
+               logg->logError("%s", buf);
+               handleException();
+       }
+       close(pipefd[0]);
 
-       return 0;
+       // Exit so parent shell can move on
+       exit(0);
 }
index 280d61139784c2ed085fe99d4b9222a00dc131e6..427e71788c3699be9023b1cf54b92d87d75e2bd3 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2014. All rights reserved.
+ * Copyright (C) ARM Limited 2014-2015. All rights reserved.
  *
  * 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
@@ -13,6 +13,6 @@
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
 
 bool getLinuxVersion(int version[3]);
-int update(const char *const gatorPath);
+void update(const char *const gatorPath);
 
 #endif // SETUP_H
index 60cf704e599b5f391af008e7d8969fa5a0200fba..64d6206895b0f755176a47931269885255f970a9 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -18,7 +18,7 @@ Source::~Source() {
 
 void Source::start() {
        if (pthread_create(&mThreadID, NULL, runStatic, this)) {
-               logg->logError(__FILE__, __LINE__, "Failed to create source thread");
+               logg->logError("Failed to create source thread");
                handleException();
        }
 }
index 56ac3d6e94f3f896fdad34569a9742d74aee25fd..b9369be5198b6006c35b7bf343a382f64275ddff 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 2b61eaeb290d620888c46a2d5db14be0a801ebd2..e37f2712cd04d40ce6f7e42d31d5a047733c3e69 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2011-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2011-2015. All rights reserved.
  *
  * 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
@@ -68,7 +68,7 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) {
                                sendData(NULL, 0, RESPONSE_ACK);
                                break;
                        default:
-                               logg->logError(__FILE__, __LINE__, "Target error: Unknown command type, %d", type);
+                               logg->logError("Target error: Unknown command type, %d", type);
                                handleException();
                }
 
@@ -76,7 +76,7 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) {
        }
 
        if (gSessionData->mCounterOverflow > 0) {
-               logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
+               logg->logError("Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
                handleException();
        }
 }
@@ -96,7 +96,7 @@ char* StreamlineSetup::readCommand(int* command) {
        gSessionData->mWaitingOnCommand = false;
 
        if (response < 0) {
-               logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
+               logg->logError("Target error: Unexpected socket disconnect");
                handleException();
        }
 
@@ -105,21 +105,21 @@ char* StreamlineSetup::readCommand(int* command) {
 
        // add artificial limit
        if ((length < 0) || length > 1024 * 1024) {
-               logg->logError(__FILE__, __LINE__, "Target error: Invalid length received, %d", length);
+               logg->logError("Target error: Invalid length received, %d", length);
                handleException();
        }
 
        // allocate memory to contain the xml file, size of zero returns a zero size object
        data = (char*)calloc(length + 1, 1);
        if (data == NULL) {
-               logg->logError(__FILE__, __LINE__, "Unable to allocate memory for xml");
+               logg->logError("Unable to allocate memory for xml");
                handleException();
        }
 
        // receive data
        response = mSocket->receiveNBytes(data, length);
        if (response < 0) {
-               logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
+               logg->logError("Target error: Unexpected socket disconnect");
                handleException();
        }
 
@@ -222,7 +222,7 @@ void StreamlineSetup::sendDefaults() {
 
        // Artificial size restriction
        if (size > 1024*1024) {
-               logg->logError(__FILE__, __LINE__, "Corrupt default configuration file");
+               logg->logError("Corrupt default configuration file");
                handleException();
        }
 
@@ -241,7 +241,7 @@ void StreamlineSetup::sendCounters() {
        }
 
        if (count == 0) {
-               logg->logError(__FILE__, __LINE__, "No counters found, this could be because /dev/gator/events can not be read or because perf is not working correctly");
+               logg->logError("No counters found, this could be because /dev/gator/events can not be read or because perf is not working correctly");
                handleException();
        }
 
@@ -258,7 +258,7 @@ void StreamlineSetup::writeConfiguration(char* xml) {
        ConfigurationXML::getPath(path);
 
        if (util->writeToDisk(path, xml) < 0) {
-               logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify write permissions to this path.", path);
+               logg->logError("Error writing %s\nPlease verify write permissions to this path.", path);
                handleException();
        }
 
@@ -266,7 +266,7 @@ void StreamlineSetup::writeConfiguration(char* xml) {
        { ConfigurationXML configuration; }
 
        if (gSessionData->mCounterOverflow > 0) {
-               logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
+               logg->logError("Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
                handleException();
        }
 }
index 623e14f2b64a7c1bb68521464fc2f8e89dd8f8c5..d8b16260643679501cdcca63b7dc3a515b5c8027 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index f94a995393e844f5675ac1e67b160855281033fb..6a69f5ab137ec880f7cd26ba79ffd8e3fd907c10 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
@@ -34,7 +34,7 @@ UEvent::~UEvent() {
 bool UEvent::init() {
        mFd = socket_cloexec(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
        if (mFd < 0) {
-               logg->logMessage("%s(%s:%i): socket failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("socket failed");
                return false;
        }
 
@@ -44,7 +44,7 @@ bool UEvent::init() {
        sockaddr.nl_groups = 1; // bitmask: (1 << 0) == kernel events, (1 << 1) == udev events
        sockaddr.nl_pid = 0;
        if (bind(mFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0) {
-               logg->logMessage("%s(%s:%i): bind failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("bind failed");
                return false;
        }
 
@@ -54,7 +54,7 @@ bool UEvent::init() {
 bool UEvent::read(UEventResult *const result) {
        ssize_t bytes = recv(mFd, result->mBuf, sizeof(result->mBuf), 0);
        if (bytes <= 0) {
-               logg->logMessage("%s(%s:%i): recv failed", __FUNCTION__, __FILE__, __LINE__);
+               logg->logMessage("recv failed");
                return false;
        }
 
@@ -64,6 +64,7 @@ bool UEvent::read(UEventResult *const result) {
 
        for (int pos = 0; pos < bytes; pos += strlen(result->mBuf + pos) + 1) {
                char *const str = result->mBuf + pos;
+               logg->logMessage("uevent + %i: %s", pos, str);
                if (strncmp(str, ACTION, sizeof(ACTION) - 1) == 0) {
                        result->mAction = str + sizeof(ACTION) - 1;
                } else if (strncmp(str, DEVPATH, sizeof(DEVPATH) - 1) == 0) {
index 2f7ef2c93f5da1348a8282e78f102fabce113c79..4c00f6cff1125aa4535e4771b4b6ab0e2f5c5e7e 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2015. All rights reserved.
  *
  * 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
index 4a9b22f4b555d66e39057004fe6d3ebdb6188b93..f58f828e6e2ebafee9ae2d8c31d0400253f8472e 100644 (file)
@@ -1,13 +1,16 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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.
  */
 
+#define __STDC_FORMAT_MACROS
+
 #include "UserSpaceSource.h"
 
+#include <inttypes.h>
 #include <sys/prctl.h>
 #include <unistd.h>
 
@@ -35,45 +38,45 @@ void UserSpaceSource::run() {
                gSessionData->usDrivers[i]->start();
        }
 
-       int64_t monotonic_started = 0;
-       while (monotonic_started <= 0) {
+       int64_t monotonicStarted = 0;
+       while (monotonicStarted <= 0 && gSessionData->mSessionIsActive) {
                usleep(10);
 
                if (gSessionData->perf.isSetup()) {
-                       monotonic_started = gSessionData->mMonotonicStarted;
+                       monotonicStarted = gSessionData->mMonotonicStarted;
                } else {
-                       if (DriverSource::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
-                               logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
+                       if (DriverSource::readInt64Driver("/dev/gator/started", &monotonicStarted) == -1) {
+                               logg->logError("Error reading gator driver start time");
                                handleException();
                        }
-                       gSessionData->mMonotonicStarted = monotonic_started;
+                       gSessionData->mMonotonicStarted = monotonicStarted;
                }
        }
 
-       uint64_t next_time = 0;
+       uint64_t nextTime = 0;
        while (gSessionData->mSessionIsActive) {
-               const uint64_t curr_time = getTime() - monotonic_started;
+               const uint64_t currTime = getTime() - monotonicStarted;
                // Sample ten times a second ignoring gSessionData->mSampleRate
-               next_time += NS_PER_S/10;//gSessionData->mSampleRate;
-               if (next_time < curr_time) {
-                       logg->logMessage("Too slow, curr_time: %lli next_time: %lli", curr_time, next_time);
-                       next_time = curr_time;
+               nextTime += NS_PER_S/10;//gSessionData->mSampleRate;
+               if (nextTime < currTime) {
+                       logg->logMessage("Too slow, currTime: %" PRIi64 " nextTime: %" PRIi64, currTime, nextTime);
+                       nextTime = currTime;
                }
 
-               if (mBuffer.eventHeader(curr_time)) {
+               if (mBuffer.eventHeader(currTime)) {
                        for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) {
                                gSessionData->usDrivers[i]->read(&mBuffer);
                        }
                        // Only check after writing all counters so that time and corresponding counters appear in the same frame
-                       mBuffer.check(curr_time);
+                       mBuffer.check(currTime);
                }
 
-               if (mBuffer.bytesAvailable() <= 0) {
+               if (gSessionData->mOneShot && gSessionData->mSessionIsActive && (mBuffer.bytesAvailable() <= 0)) {
                        logg->logMessage("One shot (counters)");
                        child->endSession();
                }
 
-               usleep((next_time - curr_time)/NS_PER_US);
+               usleep((nextTime - currTime)/NS_PER_US);
        }
 
        mBuffer.setDone();
index 9b3666016dc5b5836c6c4bdf9bf933c4af82e53a..0038dcb4c3d581054bcfaabee399c1cae70ec346 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 6041e5e96469b2b2e307ffb4f58ecf718f9e28b5..caf6f1efdcde286b2576b206ea4ae10b45ab837b 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * Minimal set of C++ functions so that libstdc++ is not required
  *
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 769a92e51a35d002ebaa9bb82e50e112b87ac81e..0d5a0a835d2cf517b6468026d803ba8e67d9b0f7 100644 (file)
@@ -6,7 +6,7 @@
 # -std=c++0x is the planned new c++ standard
 # -std=c++98 is the 1998 c++ standard
 CPPFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors
-CXXFLAGS += -fno-rtti -Wextra # -Weffc++
+CXXFLAGS += -fno-rtti -Wextra -Wshadow # -Weffc++
 ifeq ($(WERROR),1)
        CPPFLAGS += -Werror
 endif
@@ -41,7 +41,10 @@ libsensors/conf-parse.c: ;
 %.o: %.cpp
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
 
-$(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o)
+SrcMd5.cpp: $(wildcard *.cpp *.h mxml/*.c mxml/*.h libsensors/*.c libsensors/*.h)
+       echo 'extern const char *const gSrcMd5 = "'`ls $^ | grep -Ev '^(.*_xml\.h|$@)$$' | LC_ALL=C sort | xargs cat | md5sum | cut -b 1-32`'";' > $@
+
+$(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) SrcMd5.o
        $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
 
 # Intentionally ignore CC as a native binary is required
@@ -49,4 +52,4 @@ escape: escape.c
        gcc $^ -o $@
 
 clean:
-       rm -f *.d *.o mxml/*.d mxml/*.o libsensors/*.d libsensors/*.o $(TARGET) escape events.xml events_xml.h defaults_xml.h
+       rm -f *.d *.o mxml/*.d mxml/*.o libsensors/*.d libsensors/*.o $(TARGET) escape events.xml events_xml.h defaults_xml.h SrcMd5.cpp
index 086eca1e804e805059660350a55809e6d0f7b625..31b127cdcfc63103dd133e1180cb42793bb9958f 100644 (file)
   <configuration counter="ARM_Cortex-A57_cnt1" event="0x16"/>
   <configuration counter="ARM_Cortex-A57_cnt2" event="0x10"/>
   <configuration counter="ARM_Cortex-A57_cnt3" event="0x19"/>
+  <configuration counter="ARM_Cortex-A72_ccnt" event="0x11"/>
+  <configuration counter="ARM_Cortex-A72_cnt0" event="0x8"/>
+  <configuration counter="ARM_Cortex-A72_cnt1" event="0x16"/>
+  <configuration counter="ARM_Cortex-A72_cnt2" event="0x10"/>
+  <configuration counter="ARM_Cortex-A72_cnt3" event="0x19"/>
   <configuration counter="Scorpion_ccnt" event="0xff"/>
   <configuration counter="Scorpion_cnt0" event="0x08"/>
   <configuration counter="Scorpion_cnt1" event="0x10"/>
   <configuration counter="ARM_Mali-Midgard_fragment" cores="1"/>
   <configuration counter="ARM_Mali-Midgard_vertex" cores="1"/>
   <configuration counter="ARM_Mali-Midgard_opencl" cores="1"/>
-  <configuration counter="ARM_Mali-T60x_GPU_ACTIVE"/>
-  <configuration counter="ARM_Mali-T60x_JS0_ACTIVE"/>
-  <configuration counter="ARM_Mali-T60x_JS1_ACTIVE"/>
-  <configuration counter="ARM_Mali-T60x_JS2_ACTIVE"/>
-  <configuration counter="ARM_Mali-T62x_GPU_ACTIVE"/>
-  <configuration counter="ARM_Mali-T62x_JS0_ACTIVE"/>
-  <configuration counter="ARM_Mali-T62x_JS1_ACTIVE"/>
-  <configuration counter="ARM_Mali-T62x_JS2_ACTIVE"/>
-  <configuration counter="ARM_Mali-T72x_GPU_ACTIVE"/>
-  <configuration counter="ARM_Mali-T72x_JS0_ACTIVE"/>
-  <configuration counter="ARM_Mali-T72x_JS1_ACTIVE"/>
-  <configuration counter="ARM_Mali-T72x_JS2_ACTIVE"/>
-  <configuration counter="ARM_Mali-T76x_GPU_ACTIVE"/>
-  <configuration counter="ARM_Mali-T76x_JS0_ACTIVE"/>
-  <configuration counter="ARM_Mali-T76x_JS1_ACTIVE"/>
-  <configuration counter="ARM_Mali-T76x_JS2_ACTIVE"/>
   <configuration counter="L2C-310_cnt0" event="0x1"/>
 </configurations>
index 2b0863aaf4250058edc835e45fe84208900bb99f..99f434848cb3f5128e12234465284cf783bcd339 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
index 57e3235463145a20e36ae9be3767a8ed22f23eff..e481267b21ae83332bfed0913594b1ef9d516bce 100644 (file)
@@ -16,7 +16,7 @@
     <event event="0x0d" title="Program Counter" name="SW change" description="Software changed the PC"/>
     <event event="0x0f" title="Cache " name="TLB miss" description="Main TLB miss (unused on ARM1156)"/>
     <event event="0x10" title="External" name="Access" description="Explicit external data or peripheral access"/>
-    <event event="0x11" title="Cache" name="Data miss" description="Stall because of Load Store Unit request queue being full"/>
+    <event event="0x11" title="Cache" name="Stall" description="Stall because of Load Store Unit request queue being full"/>
     <event event="0x12" title="Write Buffer" name="Drains" description="The number of times the Write Buffer was drained because of a Data Synchronization Barrier command or Strongly Ordered operation"/>
     <event event="0x13" title="Disable Interrupts" name="FIQ" description="The number of cycles which FIQ interrupts are disabled (ARM1156 only)"/>
     <event event="0x14" title="Disable Interrupts" name="IRQ" description="The number of cycles which IRQ interrupts are disabled (ARM1156 only)"/>
index 20002efd1543f6210ce10aea20ab01bd0e85bdb9..40d91e582c198ca0dde3d4c6418d43eec249e71f 100644 (file)
@@ -1,5 +1,5 @@
   <counter_set name="CCI_400_cnt" count="4"/>
-  <category name="CCI-400" counter_set="CCI_400_cnt" per_cpu="no" supports_event_based_sampling="yes">
+  <category name="CCI-400" counter_set="CCI_400_cnt" per_cpu="no">
     <event counter="CCI_400_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
     <option_set name="Slave">
       <option event_delta="0x00" name="S0" description="Slave interface 0"/>
@@ -42,7 +42,7 @@
     <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/>
   </category>
   <counter_set name="CCI_400-r1_cnt" count="4"/>
-  <category name="CCI-400" counter_set="CCI_400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes">
+  <category name="CCI-400" counter_set="CCI_400-r1_cnt" per_cpu="no">
     <event counter="CCI_400-r1_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
     <option_set name="Slave">
       <option event_delta="0x00" name="S0" description="Slave interface 0"/>
diff --git a/tools/gator/daemon/events-CCI-500.xml b/tools/gator/daemon/events-CCI-500.xml
new file mode 100644 (file)
index 0000000..e7cadc4
--- /dev/null
@@ -0,0 +1,75 @@
+  <counter_set name="CCI_500_cnt" count="8"/>
+  <category name="CCI-500" counter_set="CCI_500_cnt" per_cpu="no">
+    <option_set name="Slave">
+      <option event_delta="0x00" name="S0" description="Slave interface 0"/>
+      <option event_delta="0x20" name="S1" description="Slave interface 1"/>
+      <option event_delta="0x40" name="S2" description="Slave interface 2"/>
+      <option event_delta="0x60" name="S3" description="Slave interface 3"/>
+      <option event_delta="0x80" name="S4" description="Slave interface 4"/>
+      <option event_delta="0xa0" name="S5" description="Slave interface 5"/>
+      <option event_delta="0xc0" name="S6" description="Slave interface 6"/>
+    </option_set>
+    <event event="0x00" option_set="Slave" title="CCI-500" name="Read ARVALID" description="Read request handshake: any ARVALID, ARREADY HIGH"/>
+    <event event="0x01" option_set="Slave" title="CCI-500" name="Read device" description="Read request: device"/>
+    <event event="0x02" option_set="Slave" title="CCI-500" name="Read non-shareable" description="Read request handshake: normal, non-shareable"/>
+    <event event="0x03" option_set="Slave" title="CCI-500" name="Read non-allocating" description="Read request handshake: normal, shareable, non-allocating, for example ReadOnce"/>
+    <event event="0x04" option_set="Slave" title="CCI-500" name="Read other" description="Read request handshake: normal, shareable allocating, for example ReadClean, ReadShared, ReadNotSharedDirty, ReadUnique"/>
+    <event event="0x05" option_set="Slave" title="CCI-500" name="Read invalidation" description="Read request handshake: invalidation, for example MakeUnique, CleanUnique"/>
+    <event event="0x06" option_set="Slave" title="CCI-500" name="Read maintenance" description="Read request handshake: cache maintenance operation, for example CleanInvalid, MakeInvalid, CleanShared"/>
+    <event event="0x07" option_set="Slave" title="CCI-500" name="Read DVM" description="Read request handshake: DVM message, any"/>
+    <event event="0x08" option_set="Slave" title="CCI-500" name="Read RVALID" description="Read data handshake: any RVALID, RREADY HIGH"/>
+    <event event="0x09" option_set="Slave" title="CCI-500" name="Read RLAST" description="Read data handshake with RLAST set, for a snoop hit"/>
+    <event event="0x0a" option_set="Slave" title="CCI-500" name="Write AWVALID" description="Write request: any AWVALID, AWREADY HIGH"/>
+    <event event="0x0b" option_set="Slave" title="CCI-500" name="Write device" description="Write request: device"/>
+    <event event="0x0c" option_set="Slave" title="CCI-500" name="Write non-shareable" description="Write request: non-shareable"/>
+    <event event="0x0d" option_set="Slave" title="CCI-500" name="Write shareable a" description="Write request handshake: shareable, for example WriteBack, WriteClean"/>
+    <event event="0x0e" option_set="Slave" title="CCI-500" name="Write shareable b" description="Write request handshake: shareable, for example WriteLineUnique"/>
+    <event event="0x0f" option_set="Slave" title="CCI-500" name="Write shareable c" description="Write request handshake: shareable, for example WriteUnique"/>
+    <event event="0x10" option_set="Slave" title="CCI-500" name="Write evict" description="Write request handshake, for example Evict"/>
+    <!--event event="0x11" option_set="Slave" title="CCI-500" name="Write evict ?" description="Write request handshake, for example WriteEvict. WriteEvict is not supported in the CCI-500, so does not fire."/-->
+    <event event="0x12" option_set="Slave" title="CCI-500" name="Write WVALID" description="Write data beat: any WVALID, WREADY HIGH"/>
+    <event event="0x13" option_set="Slave" title="CCI-500" name="Snoop ACVLID" description="Snoop request: any ACVALID, ACREADY HIGH"/>
+    <event event="0x14" option_set="Slave" title="CCI-500" name="Snoop read" description="Snoop request: read, for example ReadOnce, ReadClean, ReadNotSharedDirty, ReadShared, ReadUnique"/>
+    <event event="0x15" option_set="Slave" title="CCI-500" name="Snoop invalidate" description="Snoop request: clean or invalidate, for example MakeInvalid, CleanInvalid, CleanShared"/>
+    <event event="0x16" option_set="Slave" title="CCI-500" name="Snoop CRRESP" description="Snoop request: Data Transfer bit CRRESP[0] LOW"/>
+    <event event="0x17" option_set="Slave" title="CCI-500" name="Read request stall" description="Read request stall: ARVALID HIGH ARREADY LOW"/>
+    <event event="0x18" option_set="Slave" title="CCI-500" name="Read data stall" description="Read data stall: RVALID HIGH RREADY LOW"/>
+    <event event="0x19" option_set="Slave" title="CCI-500" name="Write request stall" description="Write request stall: AWVALID HIGH AWREADY LOW"/>
+    <event event="0x1a" option_set="Slave" title="CCI-500" name="Write data stall" description="Write data stall: WVALID HIGH WREADY LOW"/>
+    <event event="0x1b" option_set="Slave" title="CCI-500" name="Write response stall" description="Write response stall: BVALID HIGH BREADY LOW"/>
+    <event event="0x1c" option_set="Slave" title="CCI-500" name="Snoop request stall" description="Snoop request stall: ACVALID HIGH ACREADY LOW"/>
+    <event event="0x1d" option_set="Slave" title="CCI-500" name="Snoop data stall" description="Snoop data stall: CDVALID HIGH CDREADY LOW"/>
+    <event event="0x1e" option_set="Slave" title="CCI-500" name="Request stall" description="Request stall cycle because of OT transaction limit"/>
+    <event event="0x1f" option_set="Slave" title="CCI-500" name="Read stall" description="Read stall because of arbitration"/>
+    <option_set name="Master">
+      <option event_delta="0x100" name="M0" description="Master interface 0"/>
+      <option event_delta="0x120" name="M1" description="Master interface 1"/>
+      <option event_delta="0x140" name="M2" description="Master interface 2"/>
+      <option event_delta="0x160" name="M3" description="Master interface 3"/>
+      <option event_delta="0x180" name="M4" description="Master interface 4"/>
+      <option event_delta="0x1a0" name="M5" description="Master interface 5"/>
+    </option_set>
+    <event event="0x00" option_set="Master" title="CCI-500" name="Read data beat" description="Read data beat: any"/>
+    <event event="0x01" option_set="Master" title="CCI-500" name="Write data beat" description="Write data beat: any"/>
+    <event event="0x02" option_set="Master" title="CCI-500" name="Read request stall" description="Read request stall: ARVALID HIGH ARREADY LOW"/>
+    <event event="0x03" option_set="Master" title="CCI-500" name="Read data stall" description="Read data stall: RVALID HIGH RREADY LOW"/>
+    <event event="0x04" option_set="Master" title="CCI-500" name="Write request stall" description="Write request stall: AWVALID HIGH AWREADY LOW"/>
+    <event event="0x05" option_set="Master" title="CCI-500" name="Write data stall" description="Write data stall: WVALID HIGH WREADY LOW"/>
+    <event event="0x06" option_set="Master" title="CCI-500" name="Write response stall" description="Write response stall: BVALID HIGH BREADY LOW"/>
+    <event event="0x1e0" title="CCI-500" name="Snoop response 0/1" description="Access to snoop filter bank 0 or 1, any response"/>
+    <event event="0x1e1" title="CCI-500" name="Snoop response 2/3" description="Access to snoop filter bank 2 or 3, any response"/>
+    <event event="0x1e2" title="CCI-500" name="Snoop response 3/4" description="Access to snoop filter bank 4 or 5, any response"/>
+    <event event="0x1e3" title="CCI-500" name="Snoop response 6/7" description="Access to snoop filter bank 6 or 7, any response"/>
+    <event event="0x1e4" title="CCI-500" name="Snoop miss 0/1" description="Access to snoop filter bank 0 or 1, miss response"/>
+    <event event="0x1e5" title="CCI-500" name="Snoop miss 2/3" description="Access to snoop filter bank 2 or 3, miss response"/>
+    <event event="0x1e6" title="CCI-500" name="Snoop miss 4/5" description="Access to snoop filter bank 4 or 5, miss response"/>
+    <event event="0x1e7" title="CCI-500" name="Snoop miss 6/7" description="Access to snoop filter bank 6 or 7, miss response"/>
+    <event event="0x1e8" title="CCI-500" name="Snoop invalidation" description="Back invalidation from snoop filter"/>
+    <event event="0x1e9" title="CCI-500" name="Snoop small" description="Requests that allocate into a snoop filter bank might be stalled because all ways are used. The snoop filter RAM might be too small."/>
+    <event event="0x1ea" title="CCI-500" name="TT stall" description="Stall because TT full, increase TT_DEPTH parameter to avoid performance degradation"/>
+    <event event="0x1eb" title="CCI-500" name="Write request" description="CCI-generated write request"/>
+    <event event="0x1ec" title="CCI-500" name="Snoop handshake" description="CD handshake in snoop network, use this to measure snoop data bandwidth. Each event corresponds to 16 bytes of snoop data."/>
+    <event event="0x1ed" title="CCI-500" name="Address hazard" description="Request stall because of address hazard"/>
+    <event event="0x1ee" title="CCI-500" name="TT full" description="Snoop request stall because of snoop TT being full"/>
+    <event event="0x1ef" title="CCI-500" name="Snoop override" description="Snoop request type override for TZMP1 protection"/>
+  </category>
index f50e55d6619502cd2aca0e9d7ce76473a70e92cd..c0ccc8ac9c6423cd76127ace28d068ef94d2c40f 100644 (file)
@@ -1,68 +1,70 @@
   <counter_set name="ARMv7_Cortex_A15_cnt" count="6"/>
   <category name="Cortex-A15" counter_set="ARMv7_Cortex_A15_cnt" per_cpu="yes" supports_event_based_sampling="yes">
     <event counter="ARMv7_Cortex_A15_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
-    <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
+    <event event="0x00" title="Software" name="Increment" description="Instruction architecturally executed, condition code check pass, software increment"/>
     <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
     <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
     <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
     <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
     <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
     <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
-    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken"/>
+    <event event="0x0a" title="Exception" name="Return" description="Instruction architecturally executed, condition code check pass, exception return"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction architecturally executed, condition code check pass, write to CONTEXTIDR"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Mispredicted or not predicted branch speculatively executed"/>
     <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
     <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
-    <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
-    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
+    <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
+    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache write-back"/>
     <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
     <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
-    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
-    <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
+    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache write-back"/>
+    <event event="0x19" title="Bus" name="Access" description="Bus access"/>
     <event event="0x1a" title="Memory" name="Error" description="Local memory error"/>
     <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
-    <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/>
-    <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
-    <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
-    <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
-    <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
-    <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
-    <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-Back - Victim"/>
-    <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-Back - Cleaning and coherency"/>
+    <event event="0x1c" title="Memory" name="Translation table" description="Instruction architecturally executed, condition code check pass, write to TTBR"/>
+    <event event="0x1d" title="Bus" name="Cycle" description="Bus cycle"/>
+    <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access, read"/>
+    <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access, write"/>
+    <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill, read"/>
+    <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill, write"/>
+    <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache write-back, victim"/>
+    <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache write-back, cleaning and coherency"/>
     <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
-    <event event="0x4c" title="TLB" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
-    <event event="0x4d" title="TLB" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
-    <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
-    <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
-    <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
-    <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
-    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-Back - Victim"/>
-    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-Back - Cleaning and coherency"/>
+    <event event="0x4c" title="Cache" name="L1 TLB refill read" description="Level 1 data TLB refill, read"/>
+    <event event="0x4d" title="Cache" name="L1 TLB refill write" description="Level 1 data TLB refill, write"/>
+    <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access, read"/>
+    <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access, write"/>
+    <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill, read"/>
+    <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill, write"/>
+    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache write-back, victim"/>
+    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache write-back, cleaning and coherency"/>
     <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
-    <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
-    <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
-    <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
-    <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
-    <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
-    <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
-    <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
-    <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
+    <event event="0x60" title="Bus" name="Read" description="Bus access, read"/>
+    <event event="0x61" title="Bus" name="Write" description="Bus access, write"/>
+    <event event="0x62" title="Bus" name="Cacheable normal" description="Bus access, Normal, Cacheable, Shareable"/>
+    <event event="0x63" title="Bus" name="Not normal" description="Bus access, not Normal, Cacheable, Shareable"/>
+    <event event="0x64" title="Bus" name="Access normal" description="Bus access, normal"/>
+    <event event="0x65" title="Bus" name="Peripheral" description="Bus access, peripheral"/>
+    <event event="0x66" title="Memory" name="Read" description="Data memory access, read"/>
+    <event event="0x67" title="Memory" name="Write" description="Data memory access, write"/>
+    <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access, read"/>
+    <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access, write"/>
     <event event="0x6a" title="Memory" name="Unaligned" description="Unaligned access"/>
-    <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/>
-    <event event="0x6d" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
-    <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
-    <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed - Load"/>
-    <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed - Store"/>
-    <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
-    <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
-    <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
-    <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed - VFP"/>
-    <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
-    <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
-    <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
-    <event event="0x7a" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
-    <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
-    <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
-    <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
+    <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed, LDREX"/>
+    <event event="0x6d" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed, STREX pass"/>
+    <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed, STREX fail"/>
+    <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed, load"/>
+    <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed, store"/>
+    <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed, load or store"/>
+    <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed, integer data processing"/>
+    <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed, Advanced SIMD Extension"/>
+    <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed, Floating-point Extension"/>
+    <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed, software change of the PC"/>
+    <event event="0x78" title="Branch" name="Immediate" description="Branch speculatively executed, immediate branch"/>
+    <event event="0x79" title="Procedure" name="Return" description="Branch speculatively executed, procedure return"/>
+    <event event="0x7a" title="Branch" name="Indirect" description="Branch speculatively executed, indirect branch"/>
+    <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed, ISB"/>
+    <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed, DSB"/>
+    <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed, DMB"/>
   </category>
index 4dd08c1f203d9c4ee11aeb254a8e7276db5abc9c..ce1b7810104cac94f760834b98e7214ee223cb3c 100644 (file)
@@ -1,37 +1,36 @@
   <counter_set name="ARMv7_Cortex_A17_cnt" count="6"/>
   <category name="Cortex-A17" counter_set="ARMv7_Cortex_A17_cnt" per_cpu="yes" supports_event_based_sampling="yes">
     <event counter="ARMv7_Cortex_A17_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
-    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
-    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
-    <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
-    <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
+    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill at (at least) the lowest level of instruction or unified cache. Includes the speculative linefills in the count."/>
+    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill at (at least) the lowest level of TLB. Includes the speculative requests in the count."/>
+    <event event="0x03" title="Cache" name="Data refill" description="Data read or write operation that causes a refill at (at least) the lowest level of data or unified cache. Counts the number of allocations performed in the Data Cache because of a read or a write."/>
+    <event event="0x04" title="Cache" name="Data access" description="Data read or write operation that causes a cache access at (at least) the lowest level of data or unified cache. This includes speculative reads."/>
+    <event event="0x05" title="Cache" name="Data TLB refill" description="Data read or write operation that causes a TLB refill at (at least) the lowest level of TLB. This does not include micro TLB misses because of PLD, PLI, CP15 Cache operation by MVA and CP15 VA to PA operations."/>
     <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken. Counts the number of exceptions architecturally taken."/>
     <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
-    <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
-    <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
-    <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
-    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Change to ContextID retired. Counts the number of instructions architecturally executed writing into the ContextID register."/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted. Counts the number of mispredicted or not-predicted branches executed. This includes the branches which are flushed because of a previous load/store which aborts late."/>
+    <event event="0x12" title="Branch" name="Potential prediction" description="Branches or other change in program flow that could have been predicted by the branch prediction resources of the processor. This includes the branches which are flushed because of a previous load/store which aborts late."/>
+    <event event="0x13" title="Memory" name="Memory access" description="Level 1 data memory access"/>
+    <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
+    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache eviction"/>
     <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
     <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
-    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
-    <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
-    <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
-    <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/>
-    <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
+    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache write-back. Data transfers made as a result of a coherency request from the Level 2 caches to outside of the Level 1 and Level 2 caches are not counted. Write-backs made as a result of CP15 cache maintenance operations are counted."/>
+    <event event="0x19" title="Bus" name="Access" description="Bus accesses. Single transfer bus accesses on either of the ACE read or write channels might increment twice in one cycle if both the read and write channels are active simultaneously.Operations that utilise the bus that do not explicitly transfer data, such as barrier or coherency operations are counted as bus accesses."/>
+    <event event="0x1b" title="Instruction" name="Speculative" description="Instructions speculatively executed"/>
+    <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table register (TTBR0 or TTBR1)"/>
+    <event event="0x1d" title="Bus" name="Cycle" description="Bus cycle"/>
     <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
     <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
     <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
     <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
-    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-Back - Victim"/>
-    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-Back - Cleaning and coherency"/>
+    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache write-back - Victim"/>
+    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache write-back - Cleaning and coherency"/>
     <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
-    <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
-    <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
-    <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
+    <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal Cacheable"/>
+    <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not Cacheable"/>
     <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
     <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
     <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
     <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/>
     <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
     <event event="0x6f" title="Intrinsic" name="STREX" description="Exclusive instruction speculatively executed - STREX"/>
-    <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed - Load"/>
-    <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed - Store"/>
+    <event event="0x70" title="Instruction" name="Load" description="Load instruction speculatively executed"/>
+    <event event="0x71" title="Instruction" name="Store" description="Store instruction speculatively executed"/>
     <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
-    <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
+    <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Data processing"/>
     <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
     <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed - VFP"/>
     <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
-    <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
-    <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
-    <event event="0x7a" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
+    <event event="0x78" title="Branch" name="Immediate" description="Branch speculatively executed - Immediate branch"/>
+    <event event="0x79" title="Procedure" name="Return" description="Branch speculatively executed - Procedure return"/>
+    <event event="0x7a" title="Branch" name="Indirect" description="Branch speculatively executed - Indirect branch"/>
     <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
     <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
     <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
-    <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
-    <event event="0x8a" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
-    <event event="0xc0" title="Instruction" name="Stalled Linefill" description="Instruction side stalled due to a Linefill"/>
-    <event event="0xc1" title="Instruction" name="Stalled Page Table Walk" description="Instruction Side stalled due to a Page Table Walk"/>
+    <event event="0x81" title="Exception" name="Undefined" description="Exception taken - Undefined Instruction"/>
+    <event event="0x8a" title="Exception" name="Hypervisor call" description="Exception taken - Hypervisor Call"/>
+    <event event="0xc0" title="Instruction" name="Stalled Linefill" description="Instruction side stalled due to a linefill"/>
+    <event event="0xc1" title="Instruction" name="Stalled Page Table Walk" description="Instruction side stalled due to a translation table walk"/>
     <event event="0xc2" title="Cache" name="4 Ways Read" description="Number of set of 4 ways read in the instruction cache - Tag RAM"/>
     <event event="0xc3" title="Cache" name="Ways Read" description="Number of ways read in the instruction cache - Data RAM"/>
     <event event="0xc4" title="Cache" name="BATC Read" description="Number of ways read in the instruction BTAC RAM"/>
-    <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A17 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data"/>
+    <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A17 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data."/>
     <event event="0xd3" title="Slots" name="Load-Store Unit" description="Duration during which all slots in the Load-Store Unit are busy"/>
     <event event="0xd8" title="Slots" name="Load-Store Issue Queue" description="Duration during which all slots in the Load-Store Issue queue are busy"/>
     <event event="0xd9" title="Slots" name="Data Processing Issue Queue" description="Duration during which all slots in the Data Processing issue queue are busy"/>
     <event event="0xdc" title="Hypervisor" name="Traps" description="Number of Trap to hypervisor"/>
     <event event="0xde" title="PTM" name="EXTOUT 0" description="PTM EXTOUT 0"/>
     <event event="0xdf" title="PTM" name="EXTOUT 1" description="PTM EXTOUT 1"/>
-    <event event="0xe0" title="MMU" name="Table Walk" description="Duration during which the MMU handle a Page table walk"/>
-    <event event="0xe1" title="MMU" name="Stage1 Table Walk" description="Duration during which the MMU handle a Stage1 Page table walk"/>
-    <event event="0xe2" title="MMU" name="Stage2 Table Walk" description="Duration during which the MMU handle a Stage2 Page table walk"/>
-    <event event="0xe3" title="MMU" name="LSU Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Load Store Unit"/>
-    <event event="0xe4" title="MMU" name="Instruction Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Instruction side"/>
-    <event event="0xe5" title="MMU" name="Preload Table Walk" description="Duration during which the MMU handle a Page table walk requested by a Preload instruction or Prefetch request"/>
-    <event event="0xe6" title="MMU" name="cp15 Table Walk" description="Duration during which the MMU handle a Page table walk requested by a cp15 operation (maintenance by MVA and VA-to-PA operation)"/>
+    <event event="0xe0" title="MMU" name="Table Walk" description="Duration during which the MMU handle a translation table walk"/>
+    <event event="0xe1" title="MMU" name="Stage1 Table Walk" description="Duration during which the MMU handle a Stage1 translation table walk"/>
+    <event event="0xe2" title="MMU" name="Stage2 Table Walk" description="Duration during which the MMU handle a Stage2 translation table walk"/>
+    <event event="0xe3" title="MMU" name="LSU Table Walk" description="Duration during which the MMU handle a translation table walk requested by the Load Store Unit"/>
+    <event event="0xe4" title="MMU" name="Instruction Table Walk" description="Duration during which the MMU handle a translation table walk requested by the Instruction side"/>
+    <event event="0xe5" title="MMU" name="Preload Table Walk" description="Duration during which the MMU handle a translation table walk requested by a Preload instruction or Prefetch request"/>
+    <event event="0xe6" title="MMU" name="cp15 Table Walk" description="Duration during which the MMU handle a translation table walk requested by a CP15 operation (maintenance by MVA and VA-to-PA operation)"/>
     <event event="0xe7" title="Cache" name="L1 PLD TLB refill" description="Level 1 PLD TLB refill"/>
     <event event="0xe8" title="Cache" name="L1 CP15 TLB refill" description="Level 1 CP15 TLB refill"/>
     <event event="0xe9" title="Cache" name="L1 TLB flush" description="Level 1 TLB flush"/>
index d67581d77c08d3b41ac6a979138e69bdb2d0ceb9..9fd48abbd571a4924b9df37e20dc357d8a932d7f 100644 (file)
@@ -1,36 +1,36 @@
   <counter_set name="ARMv7_Cortex_A5_cnt" count="2"/>
   <category name="Cortex-A5" counter_set="ARMv7_Cortex_A5_cnt" per_cpu="yes" supports_event_based_sampling="yes">
     <event counter="ARMv7_Cortex_A5_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
-    <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
-    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
-    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
-    <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
-    <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
-    <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
+    <event event="0x00" title="Software" name="Increment" description="Software increment. The register is incremented only on writes to the Software Increment Register."/>
+    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill at (at least) the lowest level of instruction or unified cache. Includes the speculative linefills in the count."/>
+    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill at (at least) the lowest level of TLB. Includes the speculative requests in the count."/>
+    <event event="0x03" title="Cache" name="Data refill" description="Data read or write operation that causes a refill at (at least) the lowest level of data or unified cache. Counts the number of allocations performed in the Data Cache because of a read or a write."/>
+    <event event="0x04" title="Cache" name="Data access" description="Data read or write operation that causes a cache access at (at least) the lowest level of data or unified cache. This includes speculative reads."/>
+    <event event="0x05" title="Cache" name="Data TLB refill" description="Data read or write operation that causes a TLB refill at (at least) the lowest level of TLB. This does not include micro TLB misses because of PLD, PLI, CP15 Cache operation by MVA and CP15 VA to PA operations."/>
+    <event event="0x06" title="Instruction" name="Memory read" description="Data read architecturally executed. Counts the number of data read instructions accepted by the Load Store Unit. This includes counting the speculative and aborted LDR/LDM, and the reads because of the SWP instructions."/>
+    <event event="0x07" title="Instruction" name="Memory write" description="Data write architecturally executed. Counts the number of data write instructions accepted by the Load Store Unit. This includes counting the speculative and aborted STR/STM, and the writes because of the SWP instructions."/>
     <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken. Counts the number of exceptions architecturally taken."/>
     <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
-    <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
-    <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/>
-    <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
-    <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Change to ContextID retired. Counts the number of instructions architecturally executed writing into the ContextID Register."/>
+    <event event="0x0c" title="Branch" name="PC change" description="Software change of PC"/>
+    <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed (taken or not taken). This includes the branches which are flushed due to a previous load/store which aborts late."/>
+    <event event="0x0e" title="Procedure" name="Return" description="Procedure return (other than exception returns) architecturally executed"/>
+    <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned load-store"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted/not predicted. Counts the number of mispredicted or not-predicted branches executed. This includes the branches which are flushed because of a previous load/store which aborts late."/>
+    <event event="0x12" title="Branch" name="Potential prediction" description="Branches or other change in program flow that could have been predicted by the branch prediction resources of the processor. This includes the branches which are flushed because of a previous load/store which aborts late."/>
     <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
-    <event event="0x14" title="Cache" name="Instruction access" description="Instruction cache access"/>
+    <event event="0x14" title="Cache" name="Instruction access" description="Instruction Cache access"/>
     <event event="0x15" title="Cache" name="Data eviction" description="Data cache eviction"/>
     <event event="0x86" title="Interrupts" name="IRQ" description="IRQ exception taken"/>
     <event event="0x87" title="Interrupts" name="FIQ" description="FIQ exception taken"/>
-    <event event="0xC0" title="Memory" name="External request" description="External memory request"/>
-    <event event="0xC1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
-    <event event="0xC2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
-    <event event="0xC3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
-    <event event="0xC4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
-    <event event="0xC5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
-    <event event="0xC7" title="ETM" name="ETM Ext Out[0]" description="ETM - ETM Ext Out[0]"/>
-    <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description="ETM - ETM Ext Out[1]"/>
-    <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
+    <event event="0xc0" title="Memory" name="External request" description="External memory request"/>
+    <event event="0xc1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
+    <event event="0xc2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
+    <event event="0xc3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
+    <event event="0xc4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
+    <event event="0xc5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
+    <event event="0xc7" title="ETM" name="ETM Ext Out[0]" description="ETM Ext Out[0]"/>
+    <event event="0xc8" title="ETM" name="ETM Ext Out[1]" description="ETM Ext Out[1]"/>
+    <event event="0xc9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
   </category>
index 5ba17907d5ab81cdb98d16f8667aecbe5c670d0e..acdfe4ecd2422dab820d7539b327b5dc3a78eee2 100644 (file)
@@ -1,87 +1,64 @@
   <counter_set name="ARM_Cortex-A53_cnt" count="6"/>
   <category name="Cortex-A53" counter_set="ARM_Cortex-A53_cnt" per_cpu="yes" supports_event_based_sampling="yes">
     <event counter="ARM_Cortex-A53_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
-    <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+    <event event="0x00" title="Software" name="Increment" description="Software increment. The register is incremented only on writes to the Software Increment Register."/>
     <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
     <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
     <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
     <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
     <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
+    <event event="0x06" title="Instruction" name="Data Read" description="Instruction architecturally executed, condition check pass - load"/>
+    <event event="0x07" title="Instruction" name="Memory write" description="Instruction architecturally executed, condition check pass - store"/>
     <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
-    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken"/>
+    <event event="0x0a" title="Exception" name="Return" description="Exception return"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Change to Context ID retired"/>
+    <event event="0x0c" title="Branch" name="PC change" description="Instruction architecturally executed, condition check pass, software change of the PC"/>
+    <event event="0x0d" title="Branch" name="Immediate" description="Instruction architecturally executed, immediate branch"/>
+    <event event="0x0e" title="Procedure" name="Return" description="Instruction architecturally executed, condition code check pass, procedure return"/>
+    <event event="0x0f" title="Memory" name="Unaligned access" description="Instruction architecturally executed, condition check pass, unaligned load or store"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Mispredicted or not predicted branch speculatively executed"/>
     <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
     <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
-    <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
-    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
-    <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
-    <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
-    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
+    <event event="0x14" title="Cache" name="L1 inst access" description="L1 Instruction cache access"/>
+    <event event="0x15" title="Cache" name="L1 data write" description="L1 Data cache Write-Back"/>
+    <event event="0x16" title="Cache" name="L2 data access" description="L2 Data cache access"/>
+    <event event="0x17" title="Cache" name="L2 data refill" description="L2 Data cache refill"/>
+    <event event="0x18" title="Cache" name="L2 data write" description="L2 Data cache Write-Back"/>
     <event event="0x19" title="Bus" name="Access" description="Bus access"/>
-    <event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
-    <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
-    <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
-    <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
-    <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
-    <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
-    <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
-    <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
-    <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
-    <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
-    <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
-    <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
-    <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
-    <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
-    <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
-    <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
-    <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
-    <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
-    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/>
-    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/>
-    <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
+    <event event="0x1a" title="Memory" name="Error" description="Local memory error"/>
+    <event event="0x1d" title="Bus" name="Cycle" description="Bus cycle"/>
+    <event event="0x1e" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
     <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
     <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
-    <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
-    <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
-    <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
-    <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
-    <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
-    <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
-    <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
-    <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
-    <event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/>
-    <event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
-    <event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
-    <event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
-    <event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/>
-    <event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/>
-    <event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/>
-    <event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/>
-    <event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/>
-    <event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/>
-    <event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/>
-    <event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/>
-    <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
-    <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
-    <event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
-    <event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
-    <event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
-    <event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
-    <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
-    <event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/>
-    <event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/>
-    <event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/>
+    <event event="0x7a" title="Branch" name="Indirect" description="Branch speculatively executed - Indirect branch"/>
     <event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/>
     <event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/>
-    <event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/>
-    <event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
-    <event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
-    <event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/>
-    <event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
-    <event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
-    <event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
-    <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/>
-    <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/>
+    <event event="0xc0" title="Memory" name="External request" description="External memory request"/>
+    <event event="0xc1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
+    <event event="0xc2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
+    <event event="0xc3" title="Cache" name="Throttle" description="Instruction Cache Throttle occurred"/>
+    <event event="0xc4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
+    <event event="0xc5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
+    <event event="0xc6" title="Pre-decode" name="error" description="Pre-decode error"/>
+    <event event="0xc7" title="Memory" name="Write stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
+    <event event="0xc8" title="Memory" name="Snoop" description="SCU Snooped data from another CPU for this CPU"/>
+    <event event="0xc9" title="Branch" name="Taken" description="Conditional branch executed"/>
+    <!--
+    <event event="0xca" title="Branch" name="Mispredicted a" description="Indirect branch mispredicted"/>
+    <event event="0xcb" title="Branch" name="Mispredicted b" description="Indirect branch mispredicted because of address miscompare"/>
+    <event event="0xcc" title="Branch" name="Mispredicted c" description="Conditional branch mispredicted"/>
+    -->
+    <event event="0xd0" title="Cache" name="L1 inst error" description="L1 Instruction Cache (data or tag) memory error"/>
+    <event event="0xd1" title="Cache" name="L1 data error" description="L1 Data Cache (data, tag or dirty) memory error, correctable or non-correctable"/>
+    <event event="0xd2" title="Cache" name="TLB error" description="TLB memory error"/>
+    <event event="0xe0" title="Stall" name="DPU IP empty" description="Attributable Performance Impact Event. Counts every cycle that the DPU IQ is empty and that is not because of a recent micro-TLB miss, instruction cache miss or pre-decode error."/>
+    <event event="0xe1" title="Stall" name="Cache miss" description="Attributable Performance Impact Event. Counts every cycle the DPU IQ is empty and there is an instruction cache miss being processed."/>
+    <event event="0xe2" title="Stall" name="TLB miss" description="Attributable Performance Impact Event. Counts every cycle the DPU IQ is empty and there is an instruction micro-TLB miss being processed."/>
+    <event event="0xe3" title="Stall" name="Pre-decode error" description="Attributable Performance Impact Event. Counts every cycle the DPU IQ is empty and there is a pre-decode error being processed."/>
+    <event event="0xe4" title="Stall" name="Interlock other" description="Attributable Performance Impact Event. Counts every cycle there is an interlock that is not because of an Advanced SIMD or Floating-point instruction, and not because of a load/store instruction waiting for data to calculate the address in the AGU. Stall cycles because of a stall in Wr, typically awaiting load data, are excluded."/>
+    <event event="0xe5" title="Stall" name="Interlock address" description="Attributable Performance Impact Event. Counts every cycle there is an interlock that is because of a load/store instruction waiting for data to calculate the address in the AGU. Stall cycles because of a stall in Wr, typically awaiting load data, are excluded."/>
+    <event event="0xe6" title="Stall" name="Interlock SIMD/FPU" description="Attributable Performance Impact Event. Counts every cycle there is an interlock that is because of an Advanced SIMD or Floating-point instruction. Stall cycles because of a stall in the Wr stage, typically awaiting load data, are excluded."/>
+    <event event="0xe7" title="Stall" name="Load miss" description="Attributable Performance Impact Event. Counts every cycle there is a stall in the Wr stage because of a load miss"/>
+    <event event="0xe8" title="Stall" name="Store" description="Attributable Performance Impact Event. Counts every cycle there is a stall in the Wr stage because of a store."/>
   </category>
index fbe96c2d4eb2935f7cb05af6216ba62022350298..1da23e7f93c23c8699bc7e850064585a06308c90 100644 (file)
@@ -8,10 +8,10 @@
     <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
     <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
     <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
-    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken"/>
+    <event event="0x0a" title="Exception" name="Return" description="Instruction architecturally executed (condition check pass) - Exception return"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Mispredicted or not predicted branch speculatively executed"/>
     <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
     <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
     <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
     <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
     <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
     <event event="0x19" title="Bus" name="Access" description="Bus access"/>
-    <event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
-    <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
-    <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
-    <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
-    <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
+    <event event="0x1a" title="Memory" name="Error" description="Local memory error"/>
+    <event event="0x1b" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
+    <event event="0x1c" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
+    <event event="0x1d" title="Bus" name="Cycle" description="Bus cycle"/>
+    <event event="0x1e" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
     <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
     <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
     <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
@@ -32,8 +32,8 @@
     <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
     <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
     <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
-    <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
-    <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
+    <event event="0x4c" title="Cache" name="L1 TLB refill read" description="Level 1 data TLB refill - Read"/>
+    <event event="0x4d" title="Cache" name="L1 TLB refill write" description="Level 1 data TLB refill - Write"/>
     <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
     <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
     <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
     <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
     <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
     <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
-    <event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/>
-    <event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
-    <event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
-    <event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
+    <event event="0x6a" title="Memory" name="Unaligned" description="Unaligned access"/>
+    <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
+    <event event="0x6d" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
+    <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
     <event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/>
     <event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/>
     <event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/>
     <event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/>
     <event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/>
     <event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/>
-    <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
-    <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
-    <event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
-    <event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
-    <event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
-    <event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
+    <event event="0x78" title="Branch" name="Immediate" description="Branch speculatively executed - Immediate branch"/>
+    <event event="0x79" title="Procedure" name="Return" description="Branch speculatively executed - Procedure return"/>
+    <event event="0x7a" title="Branch" name="Indirect" description="Branch speculatively executed - Indirect branch"/>
+    <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
+    <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
+    <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
     <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
     <event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/>
     <event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/>
     <event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/>
     <event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/>
     <event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/>
-    <event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
-    <event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
-    <event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/>
-    <event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
-    <event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
-    <event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
-    <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/>
-    <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/>
+    <event event="0x8a" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
+    <event event="0x8b" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
+    <event event="0x8c" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort, or SError not taken locally"/>
+    <event event="0x8d" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
+    <event event="0x8e" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
+    <event event="0x8f" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
+    <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load-Acquire"/>
+    <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store-Release"/>
   </category>
index 6e078b3cffa3d8562ec52bfd4cb5868670efe5c5..22fa9b7a41480a4398087f200d366d0dadf0449c 100644 (file)
@@ -1,43 +1,44 @@
   <counter_set name="ARMv7_Cortex_A7_cnt" count="4"/>
   <category name="Cortex-A7" counter_set="ARMv7_Cortex_A7_cnt" per_cpu="yes" supports_event_based_sampling="yes">
     <event counter="ARMv7_Cortex_A7_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
-    <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
-    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
-    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
-    <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
-    <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x06" title="Memory" name="Data Read" description="Data read architecturally executed"/>
-    <event event="0x07" title="Memory" name="Data Write" description="Data write architecturally executed"/>
+    <event event="0x00" title="Software" name="Increment" description="Software increment. The register is incremented only on writes to the Software Increment Register."/>
+    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill at (at least) the lowest level of instruction or unified cache. Includes the speculative linefills in the count."/>
+    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill at (at least) the lowest level of TLB. Includes the speculative requests in the count."/>
+    <event event="0x03" title="Cache" name="Data refill" description="Data read or write operation that causes a refill at (at least) the lowest level of data or unified cache. Counts the number of allocations performed in the Data Cache because of a read or a write."/>
+    <event event="0x04" title="Cache" name="Data access" description="Data read or write operation that causes a cache access at (at least) the lowest level of data or unified cache. This includes speculative reads."/>
+    <event event="0x05" title="Cache" name="Data TLB refill" description="Data read or write operation that causes a TLB refill at (at least) the lowest level of TLB. This does not include micro TLB misses because of PLD, PLI, CP15 Cache operation by MVA and CP15 VA to PA operations."/>
+    <event event="0x06" title="Instruction" name="Memory Read" description="Data read architecturally executed. Counts the number of data read instructions accepted by the Load Store Unit. This includes counting the speculative and aborted LDR/LDM, and the reads because of the SWP instructions."/>
+    <event event="0x07" title="Instruction" name="Memory write" description="Data write architecturally executed. Counts the number of data write instructions accepted by the Load Store Unit. This includes counting the speculative and aborted STR/STM, and the writes because of the SWP instructions."/>
     <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken. Counts the number of exceptions architecturally taken."/>
     <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
-    <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
-    <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
-    <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Change to ContextID retired. Counts the number of instructions architecturally executed writing into the ContextID Register."/>
+    <event event="0x0c" title="Branch" name="PC change" description="Software change of PC"/>
+    <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed (taken or not taken). This includes the branches which are flushed due to a previous load/store which aborts late."/>
+    <event event="0x0e" title="Procedure" name="Return" description="Procedure return (other than exception returns) architecturally executed"/>
+    <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned load-store"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted/not predicted. Counts the number of mispredicted or not-predicted branches executed. This includes the branches which are flushed because of a previous load/store which aborts late."/>
+    <event event="0x12" title="Branch" name="Potential prediction" description="Branches or other change in program flow that could have been predicted by the branch prediction resources of the processor. This includes the branches which are flushed because of a previous load/store which aborts late."/>
     <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
-    <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
-    <event event="0x15" title="Cache" name="L1 data eviction" description="Level 1 data cache eviction"/>
+    <event event="0x14" title="Cache" name="L1 inst access" description="Instruction Cache access"/>
+    <event event="0x15" title="Cache" name="L1 data eviction" description="Data cache eviction"/>
     <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
     <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
-    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
-    <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
-    <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
-    <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
-    <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
+    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache write-back. Data transfers made as a result of a coherency request from the Level 2 caches to outside of the Level 1 and Level 2 caches are not counted. Write-backs made as a result of CP15 cache maintenance operations are counted."/>
+    <event event="0x19" title="Bus" name="Access" description="Bus accesses. Single transfer bus accesses on either of the ACE read or write channels might increment twice in one cycle if both the read and write channels are active simultaneously. Operations that utilise the bus that do not explicitly transfer data, such as barrier or coherency operations are counted as bus accesses."/>
+    <event event="0x1d" title="Bus" name="Cycle" description="Bus cycle"/>
+    <event event="0x60" title="Bus" name="Read" description="Bus access, read"/>
+    <event event="0x61" title="Bus" name="Write" description="Bus access, write"/>
     <event event="0x86" title="Exception" name="IRQ" description="IRQ exception taken"/>
     <event event="0x87" title="Exception" name="FIQ" description="FIQ exception taken"/>
-    <event event="0xC0" title="Memory" name="External request" description="External memory request"/>
-    <event event="0xC1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
-    <event event="0xC2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
-    <event event="0xC3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
-    <event event="0xC4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
-    <event event="0xC5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
-    <event event="0xC7" title="ETM" name="ETM Ext Out[0]" description="ETM - ETM Ext Out[0]"/>
-    <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description="ETM - ETM Ext Out[1]"/>
-    <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
-    <event event="0xCA" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local cluster, rather than accessing the L2 cache or issuing an external read."/>
+    <event event="0xc0" title="Memory" name="External request" description="External memory request"/>
+    <event event="0xc1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
+    <event event="0xc2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
+    <event event="0xc3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
+    <event event="0xc4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
+    <event event="0xc5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
+    <event event="0xc7" title="ETM" name="ETM Ext Out[0]" description="ETM Ext Out[0]"/>
+    <event event="0xc8" title="ETM" name="ETM Ext Out[1]" description="ETM Ext Out[1]"/>
+    <event event="0xc9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
+    <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A7 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data."/>
   </category>
diff --git a/tools/gator/daemon/events-Cortex-A72.xml b/tools/gator/daemon/events-Cortex-A72.xml
new file mode 100644 (file)
index 0000000..31c9cf3
--- /dev/null
@@ -0,0 +1,87 @@
+  <counter_set name="ARM_Cortex_A72_cnt" count="6"/>
+  <category name="Cortex-A72" counter_set="ARM_Cortex_A72_cnt" per_cpu="yes" supports_event_based_sampling="yes">
+    <event counter="ARM_Cortex_A72_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
+    <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
+    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
+    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
+    <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
+    <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
+    <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
+    <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
+    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
+    <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
+    <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
+    <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
+    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
+    <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
+    <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
+    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
+    <event event="0x19" title="Bus" name="Access" description="Bus access"/>
+    <event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
+    <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
+    <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
+    <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
+    <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
+    <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
+    <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
+    <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
+    <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
+    <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
+    <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
+    <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
+    <event event="0x4C" title="Cache" name="L1 TLB refill read" description="Level 1 data TLB refill - Read"/>
+    <event event="0x4D" title="Cache" name="L1 TLB refill write" description="Level 1 data TLB refill - Write"/>
+    <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
+    <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
+    <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
+    <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
+    <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/>
+    <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/>
+    <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
+    <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
+    <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
+    <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
+    <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
+    <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
+    <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
+    <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
+    <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
+    <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
+    <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
+    <event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/>
+    <event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
+    <event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
+    <event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
+    <event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/>
+    <event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/>
+    <event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/>
+    <event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/>
+    <event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/>
+    <event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/>
+    <event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/>
+    <event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/>
+    <event event="0x78" title="Branch" name="Immediate" description="Branch speculatively executed - Immediate branch"/>
+    <event event="0x79" title="Procedure" name="Return" description="Branch speculatively executed - Procedure return"/>
+    <event event="0x7A" title="Branch" name="Indirect" description="Branch speculatively executed - Indirect branch"/>
+    <event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
+    <event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
+    <event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
+    <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
+    <event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/>
+    <event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/>
+    <event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/>
+    <event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/>
+    <event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/>
+    <event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/>
+    <event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
+    <event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
+    <event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/>
+    <event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
+    <event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
+    <event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
+    <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/>
+    <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/>
+  </category>
index a69e25ab2c3483f6985d924a1ea55265fd682d29..7056efd35fe3fbfa8adc84287a0222e88d658a4e 100644 (file)
@@ -2,23 +2,23 @@
   <category name="Cortex-A8" counter_set="ARMv7_Cortex_A8_cnt" per_cpu="yes" supports_event_based_sampling="yes">
     <event counter="ARMv7_Cortex_A8_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
     <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
-    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
-    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
-    <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
-    <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
-    <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
-    <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
-    <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
-    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
-    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
-    <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
-    <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
-    <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/>
-    <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
-    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
-    <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
+    <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill at the lowest level of instruction or unified cache. Each instruction fetch from normal cacheable memory that causes a refill from outside of the cache is counted. Accesses that do not cause a new cache refill, but are satisfied from refilling data of a previous miss are not counted. Where instruction fetches consist of multiple instructions, these accesses count as single events. CP15 cache maintenance operations do not count as events. This counter increments for speculative instruction fetches and for fetches of instructions that reach execution."/>
+    <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill at the lowest level of TLB. Each instruction fetch that causes a translation table walk or an access to another level of TLB caching is counted. CP15 TLB maintenance operations do not count as events. This counter increments for speculative instruction fetches and for fetches of instructions that reach execution."/>
+    <event event="0x03" title="Cache" name="Data refill" description="Data read or write operation that causes a refill at the lowest level of data or unified cache. Each data read from or write to normal cacheable memory that causes a refill from outside of the cache is counted. Accesses that do not cause a new cache refill, but are satisfied from refilling data of a previous miss are not counted. Each access to a cache line to normal cacheable memory that causes a new linefill is counted, including the multiple transaction of instructions such as LDM or STM, PUSH and POP. Write-through writes that hit in the cache do not cause a linefill and so are not counted. CP15 cache maintenance operations do not count as events. This counter increments for speculative data accesses and for data accesses that are explicitly made by instructions."/>
+    <event event="0x04" title="Cache" name="Data access" description="Data read or write operation that causes a cache access at the lowest level of data or unified cache. Each access to a cache line to normal cacheable memory is counted including the multiple transaction of instructions such as LDM or STM. CP15 cache maintenance operations do not count as events. This counter increments for speculative data accesses and for data accesses that are explicitly made by instructions."/>
+    <event event="0x05" title="Cache" name="Data TLB refill" description="Data read or write operation that causes a TLB refill at the lowest level of TLB. Each data read or write operation that causes a translation table walk or an access to another level of TLB caching is counted. CP15 TLB maintenance operations do not count as events. This counter increments for speculative data accesses and for data accesses that are explicitly made by instructions."/>
+    <event event="0x06" title="Instruction" name="Memory read" description="Data read architecturally executed. This counter increments for every instruction that explicitly read data, including SWP. This counter only increments for instructions that are unconditional or that pass their condition codes."/>
+    <event event="0x07" title="Instruction" name="Memory write" description="Data write architecturally executed. The counter increments for every instruction that explicitly wrote data, including SWP. This counter only increments for instructions that are unconditional or that pass their condition codes."/>
+    <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed. This counter counts for all instructions, including conditional instructions that fail their condition codes."/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken. This counts for each exception taken."/>
+    <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed. This counter only increments for instructions that are unconditional or that pass their condition codes."/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the Context ID Register architecturally executed. This counter only increments for instructions that are unconditional or that pass their condition codes."/>
+    <event event="0x0c" title="Branch" name="PC change" description="Software change of PC, except by an exception, architecturally executed. This counter only increments for instructions that are unconditional or that pass their condition codes."/>
+    <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed, taken or not taken. This includes B{L}, BLX, CB{N}Z, HB{L}, and HBLP. This counter counts for all immediate branch instructions that are architecturally executed, including conditional instructions that fail their condition codes."/>
+    <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception returns, architecturally executed. This counter only increments for instructions that are unconditional or that pass their condition codes."/>
+    <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed. This counts each instruction that is an access to an unaligned address. This counter only increments for instructions that are unconditional or that pass their condition codes."/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted. This counts for every pipeline flush because of a misprediction from the program flow prediction resources."/>
+    <event event="0x12" title="Branch" name="Potential prediction" description="Branches or other change in the program flow that could have been predicted by the branch prediction resources of the processor"/>
     <event event="0x40" title="Cache" name="Write buffer full" description="Any write buffer full cycle"/>
     <event event="0x41" title="Cache" name="L2 store" description="Any store that is merged in the L2 memory system"/>
     <event event="0x42" title="Cache" name="Bufferable transaction" description="Any bufferable store transaction from load/store to L2 cache, excluding eviction or cast out data"/>
     <event event="0x46" title="AXI" name="Write" description="The number of AXI write data transfers"/>
     <event event="0x47" title="Memory" name="Replay event" description="Any replay event in the memory system"/>
     <event event="0x48" title="Memory" name="Unaligned access replay" description="Any unaligned memory access that results in a replay"/>
-    <event event="0x49" title="Cache" name="L1 data hash miss" description="Any L1 data memory access that misses in the cache as a result of the hashing algorithm"/>
-    <event event="0x4a" title="Cache" name="L1 inst hash miss" description="Any L1 instruction memory access that misses in the cache as a result of the hashing algorithm"/>
-    <event event="0x4b" title="Cache" name="L1 page coloring" description="Any L1 data memory access in which a page coloring alias occurs"/>
+    <event event="0x49" title="Cache" name="L1 data hash miss" description="Any L1 data memory access that misses in the cache as a result of the hashing algorithm. The cases covered are: hash hit and physical address miss, hash hit and physical address hit in another way and hash miss and physical address hit."/>
+    <event event="0x4a" title="Cache" name="L1 inst hash miss" description="Any L1 instruction memory access that misses in the cache as a result of the hashing algorithm. The cases covered are: hash hit and physical address miss, hash hit and physical address hit in another way and hash miss and physical address hit."/>
+    <event event="0x4b" title="Cache" name="L1 page coloring" description="Any L1 data memory access in which a page coloring alias occurs. alias = virtual address [12] ! = physical address [12]. This behavior results in a data memory eviction or cast out."/>
     <event event="0x4c" title="NEON" name="L1 cache hit" description="Any NEON access that hits in the L1 data cache"/>
     <event event="0x4d" title="NEON" name="L1 cache access" description="Any NEON cacheable data accesses for L1 data cache"/>
     <event event="0x4e" title="NEON" name="L2 cache access" description="Any L2 cache accesses as a result of a NEON memory access"/>
     <event event="0x4f" title="NEON" name="L2 cache hit" description="Any NEON hit in the L2 cache"/>
     <event event="0x50" title="Cache" name="L1 inst access" description="Any L1 instruction cache access, excluding CP15 cache accesses"/>
     <event event="0x51" title="Branch" name="Return stack misprediction" description="Any return stack misprediction because of incorrect target address for a taken return stack pop"/>
-    <event event="0x52" title="Branch" name="Direction misprediction" description="Branch direction misprediction"/>
+    <event event="0x52" title="Branch" name="Direction misprediction" description="Two forms of branch direction misprediction: branch predicted taken, but was not taken and branch predicted not taken, but was taken"/>
     <event event="0x53" title="Branch" name="Taken prediction" description="Any predictable branch that is predicted to be taken"/>
     <event event="0x54" title="Branch" name="Executed and taken prediction" description="Any predictable branch that is executed and taken"/>
     <event event="0x55" title="Core" name="Operations issued" description="Number of operations issued, where an operation is either: an instruction or one operation in a sequence of operations that make up a multi-cycle instruction"/>
     <event event="0x56" title="Core" name="No issue cycles" description="Increment for every cycle that no instructions are available for issue"/>
-    <event event="0x57" title="Core" name="Issue cycles" description="For every cycle, this event counts the number of instructions issued in that cycle. Multi-cycle instructions are only counted once"/>
+    <event event="0x57" title="Core" name="Issue cycles" description="For every cycle, this event counts the number of instructions issued in that cycle. Multi-cycle instructions are only counted once."/>
     <event event="0x58" title="NEON" name="MRC data wait" description="Number of cycles the processor stalls waiting on MRC data from NEON"/>
     <event event="0x59" title="NEON" name="Full queue" description="Number of cycles that the processor stalls as a result of a full NEON instruction queue or NEON load queue"/>
     <event event="0x5a" title="NEON" name="Idle" description="Number of cycles that NEON and integer processors are both not idle"/>
index 3e7f8289062e596f5bca5fa9c6f9ed118bbda606..e17c03d7a632d77af3c6943e9ea7fc70ed5d1c96 100644 (file)
@@ -9,7 +9,7 @@
     <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
     <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
     <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
-    <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken"/>
     <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
     <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
     <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
     <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
     <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
     <event event="0x40" title="Java" name="Bytecode execute" description="Counts the number of Java bytecodes being decoded, including speculative ones"/>
-    <event event="0x41" title="Java" name="SW bytecode execute" description="Counts the number of software java bytecodes being decoded, including speculative ones"/>
-    <event event="0x42" title="Jazelle" name="Backward branch execute" description="Counts the number of Jazelle taken branches being executed"/>
-    <event event="0x50" title="Cache" name="Coherency miss" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which also miss in all the other Cortex-A9 processors, meaning that the request is sent to the external memory"/>
-    <event event="0x51" title="Cache" name="Coherency hit" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which hit in another Cortex-A9 processor, meaning that the linefill data is fetched directly from the relevant Cortex-A9 cache"/>
-    <event event="0x60" title="Cache" name="Inst dependent stall" description="Counts the number of cycles where the processor is ready to accept new instructions, but does not receive any because of the instruction side not being able to provide any and the instruction cache is currently performing at least one linefill"/>
-    <event event="0x61" title="Cache" name="Data dependent stall" description="Counts the number of cycles where the core has some instructions that it cannot issue to any pipeline, and the Load Store unit has at least one pending linefill request, and no pending TLB requests"/>
-    <event event="0x62" title="Cache" name="TLB stall" description="Counts the number of cycles where the processor is stalled waiting for the completion of translation table walks from the main TLB"/>
+    <event event="0x41" title="Java" name="SW bytecode execute" description="Counts the number of software Java bytecodes being decoded, including speculative ones"/>
+    <event event="0x42" title="Jazelle" name="Backward branch execute" description="Counts the number of Jazelle taken branches being executed. This includes the branches that are flushed because of a previous load/store that aborts late."/>
+    <event event="0x50" title="Cache" name="Coherency miss" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor that also miss in all the other Cortex-A9 processors. This means that the request is sent to the external memory."/>
+    <event event="0x51" title="Cache" name="Coherency hit" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor that hit in another Cortex-A9 processor. This means that the linefill data is fetched directly from the relevant Cortex-A9 cache."/>
+    <event event="0x60" title="Cache" name="Inst dependent stall" description="Counts the number of cycles where the processor: is ready to accept new instructions, does not receive a new instruction, because: the instruction side is unable to provide one or the instruction cache is performing at least one linefill"/>
+    <event event="0x61" title="Cache" name="Data dependent stall" description="Counts the number of cycles where the processor has some instructions that it cannot issue to any pipeline, and the Load Store unit has at least one pending linefill request, and no pending TLB requests"/>
+    <event event="0x62" title="Cache" name="TLB stall" description="Counts the number of cycles where the processor is stalled waiting for the completion of translation table walks from the main TLB. The processor stalls because the instruction side is not able to provide the instructions, or the data side is not able to provide the necessary data."/>
     <event event="0x63" title="Intrinsic" name="STREX pass" description="Counts the number of STREX instructions architecturally executed and passed"/>
     <event event="0x64" title="Intrinsic" name="STREX fail" description="Counts the number of STREX instructions architecturally executed and failed"/>
     <event event="0x65" title="Cache" name="Data eviction" description="Counts the number of eviction requests because of a linefill in the data cache"/>
     <event event="0x66" title="Pipeline" name="Issue stage no dispatch" description="Counts the number of cycles where the issue stage does not dispatch any instruction because it is empty or cannot dispatch any instructions"/>
     <event event="0x67" title="Pipeline" name="Issue stage empty" description="Counts the number of cycles where the issue stage is empty"/>
-    <event event="0x68" title="Instruction" name="Executed" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
-    <event event="0x69" title="Cache" name="Data linefills" description="Counts the number of linefills performed on the external AXI bus"/>
-    <event event="0x6A" title="Cache" name="Prefetch linefills" description="Counts the number of data linefills caused by prefetcher requests"/>
-    <event event="0x6B" title="Cache" name="Prefetch hits" description="Counts the number of cache hits in a line that belongs to a stream followed by the prefetcher"/>
-    <event event="0x6E" title="Core" name="Functions" description="Counts the number of procedure returns whose condition codes do not fail, excluding all returns from exception"/>
-    <event event="0x70" title="Instruction" name="Main execution unit" description="Counts the number of instructions being executed in the main execution pipeline of the processor, the multiply pipeline and arithmetic logic unit pipeline"/>
-    <event event="0x71" title="Instruction" name="Second execution unit" description="Counts the number of instructions being executed in the processor second execution pipeline (ALU)"/>
-    <event event="0x72" title="Instruction" name="Load/Store" description="Counts the number of instructions being executed in the Load/Store unit"/>
-    <event event="0x73" title="Instruction" name="Floating point" description="Counts the number of Floating-point instructions going through the Register Rename stage"/>
-    <event event="0x74" title="Instruction" name="NEON" description="Counts the number of NEON instructions going through the Register Rename stage"/>
+    <event event="0x68" title="Instruction" name="Executed" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and an even more approximate number of the total number of instructions architecturally executed. The approximation depends mainly on the branch misprediction rate."/>
+    <event event="0x69" title="Cache" name="Data linefills" description="Counts the number of linefills performed on the external AXI bus. This event counts all data linefill requests, caused by: loads, including speculative ones, stores, PLD, prefetch or page table walk."/>
+    <event event="0x6a" title="Cache" name="Prefetch linefills" description="Counts the number of data linefills caused by prefetcher requests"/>
+    <event event="0x6b" title="Cache" name="Prefetch hits" description="Counts the number of cache hits in a line that belongs to a stream followed by the prefetcher. This includes: lines that have been prefetched by the automatic data prefetcher and lines already present in the cache, before the prefetcher action."/>
+    <event event="0x6e" title="Procedure" name="Return" description="Counts the number of procedure returns whose condition codes do not fail, excluding all returns from exception. This count includes procedure returns that are flushed because of a previous load/store that aborts late."/>
+    <event event="0x70" title="Instruction" name="Main execution unit" description="Counts the number of instructions being executed in the main execution pipeline of the processor, the multiply pipeline and arithmetic logic unit pipeline. The counted instructions are still speculative."/>
+    <event event="0x71" title="Instruction" name="Second execution unit" description="Counts the number of instructions being executed in the processor second execution pipeline (ALU). The counted instructions are still speculative."/>
+    <event event="0x72" title="Instruction" name="Load/Store" description="Counts the number of instructions being executed in the Load/Store unit. The counted instructions are still speculative."/>
+    <event event="0x73" title="Instruction" name="Floating point" description="Counts the number of floating-point instructions going through the Register Rename stage. Instructions are still speculative in this stage."/>
+    <event event="0x74" title="Instruction" name="NEON" description="Counts the number of NEON instructions going through the Register Rename stage. Instructions are still speculative in this stage."/>
     <event event="0x80" title="Stalls" name="PLD" description="Counts the number of cycles where the processor is stalled because PLD slots are all full"/>
-    <event event="0x81" title="Stalls" name="Memory write" description="Counts the number of cycles when the processor is stalled and the data side is stalled too because it is full and executing writes to the external memory"/>
+    <event event="0x81" title="Stalls" name="Memory write" description="Counts the number of cycles when the processor is stalled. The data side is stalled also, because it is full and executes writes to the external memory."/>
     <event event="0x82" title="Stalls" name="Inst main TLB miss" description="Counts the number of stall cycles because of main TLB misses on requests issued by the instruction side"/>
     <event event="0x83" title="Stalls" name="Data main TLB miss" description="Counts the number of stall cycles because of main TLB misses on requests issued by the data side"/>
-    <event event="0x84" title="Stalls" name="Inst micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the instruction side"/>
-    <event event="0x85" title="Stalls" name="Data micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the data side"/>
-    <event event="0x86" title="Stalls" name="DMB" description="Counts the number of stall cycles because of the execution of a DMB memory barrier"/>
-    <event event="0x8A" title="Clock" name="Integer core" description="Counts the number of cycles during which the integer core clock is enabled"/>
-    <event event="0x8B" title="Clock" name="Data engine" description="Counts the number of cycles during which the Data Engine clock is enabled"/>
-    <event event="0x8C" title="Clock" name="NEON" description="Counts the number of cycles when the NEON SIMD clock is enabled"/>
-    <event event="0x8D" title="Memory" name="TLB inst allocations" description="Counts the number of TLB allocations because of Instruction requests"/>
-    <event event="0x8E" title="Memory" name="TLB data allocations" description="Counts the number of TLB allocations because of Data requests"/>
+    <event event="0x84" title="Stalls" name="Inst micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the instruction side. This event does not include main TLB miss stall cycles that are already counted in the corresponding main TLB event."/>
+    <event event="0x85" title="Stalls" name="Data micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the data side. This event does not include main TLB miss stall cycles that are already counted in the corresponding main TLB event."/>
+    <event event="0x86" title="Stalls" name="DMB" description="Counts the number of stall cycles because of the execution of a DMB. This includes all DMB instructions being executed, even speculatively."/>
+    <event event="0x8a" title="Clock" name="Integer core" description="Counts the number of cycles when the integer core clock is enabled"/>
+    <event event="0x8b" title="Clock" name="Data engine" description="Counts the number of cycles when the data engine clock is enabled"/>
+    <event event="0x8c" title="Clock" name="NEON" description="Counts the number of cycles when the NEON SIMD clock is enabled"/>
+    <event event="0x8d" title="Memory" name="TLB inst allocations" description="Counts the number of TLB allocations because of Instruction requests"/>
+    <event event="0x8e" title="Memory" name="TLB data allocations" description="Counts the number of TLB allocations because of Data requests"/>
     <event event="0x90" title="Instruction" name="ISB" description="Counts the number of ISB instructions architecturally executed"/>
     <event event="0x91" title="Instruction" name="DSB" description="Counts the number of DSB instructions architecturally executed"/>
     <event event="0x92" title="Instruction" name="DMB" description="Counts the number of DMB instructions speculatively executed"/>
     <event event="0x93" title="External" name="Interrupts" description="Counts the number of external interrupts executed by the processor"/>
-    <event event="0xA0" title="PLE" name="Cache line rq completed" description="Counts the number of PLE cache line requests completed"/>
-    <event event="0xA1" title="PLE" name="Cache line rq skipped" description="Counts the number of PLE cache line requests skipped"/>
-    <event event="0xA2" title="PLE" name="FIFO flush" description="Counts the number of PLE FIFO flush requests"/>
-    <event event="0xA3" title="PLE" name="Request completed" description="Counts the number of PLE FIFO flush completed"/>
-    <event event="0xA4" title="PLE" name="FIFO overflow" description="Counts the number of PLE FIFO flush overflowed"/>
-    <event event="0xA5" title="PLE" name="Request programmed" description="Counts the number of PLE FIFO flush program requests"/>
+    <event event="0xa0" title="PLE" name="Cache line rq completed" description="Counts the number of PLE cache line requests completed"/>
+    <event event="0xa1" title="PLE" name="Cache line rq skipped" description="Counts the number of PLE cache line requests skipped"/>
+    <event event="0xa2" title="PLE" name="FIFO flush" description="Counts the number of PLE FIFO flush requests"/>
+    <event event="0xa3" title="PLE" name="Request completed" description="Counts the number of PLE FIFO flush completed"/>
+    <event event="0xa4" title="PLE" name="FIFO overflow" description="Counts the number of PLE FIFO flush overflowed"/>
+    <event event="0xa5" title="PLE" name="Request programmed" description="Counts the number of PLE FIFO flush program requests"/>
   </category>
index 9ef61ddac811a5054ef6aff4518efce418c89677..1fa3b3bba7812bfd5ab5b32265efe4aaff633c9e 100644 (file)
@@ -1,8 +1,7 @@
   <category name="Filesystem">
     <!-- counter attribute must start with filesystem_ and be unique -->
-    <!-- regex item in () is the value shown -->
+    <!-- regex item in () is the value shown or, if the parentheses are missing, the number of times the regex matches is counted -->
     <!--
-    <event counter="filesystem_cpu1_online" path="/sys/devices/system/cpu/cpu1/online" title="online" name="cpu 1" class="absolute" description="If cpu 1 is online"/>
     <event counter="filesystem_loginuid" path="/proc/self/loginuid" title="loginuid" name="loginuid" class="absolute" description="loginuid"/>
     <event counter="filesystem_gatord_rss" path="/proc/self/stat" title="stat" name="rss" class="absolute" regex="-?[0-9]+ \(.*\) . -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ (-?[0-9]+)" units="pages" description="resident set size"/>
     <event counter="filesystem_processes" path="/proc/stat" title="proc-stat" name="processes" class="absolute" regex="processes ([0-9]+)" description="Number of processes and threads created"/>
index 923fb90334d042a29b828a033b93f33d537640f7..055847c4ca152f268bbc3f020e3d0a7b370cc252 100644 (file)
@@ -10,8 +10,8 @@
     <event event="0x8" title="L2 Cache" name="Instruction Read Request" description="Instruction read lookup to the L2 cache. Subsequently results in a hit or miss"/>
     <event event="0x9" title="L2 Cache" name="Write Allocate Miss" description="Allocation into the L2 cache caused by a write, with Write-Allocate attribute, miss"/>
     <event event="0xa" title="L2 Cache" name="Internal Prefetch Allocate" description="Allocation of a prefetch generated by L2C-310 into the L2 cache"/>
-    <event event="0xb" title="L2 Cache" name="Prefitch Hit" description="Prefetch hint hits in the L2 cache"/>
-    <event event="0xc" title="L2 Cache" name="Prefitch Allocate" description="Prefetch hint allocated into the L2 cache"/>
+    <event event="0xb" title="L2 Cache" name="Prefetch Hit" description="Prefetch hint hits in the L2 cache"/>
+    <event event="0xc" title="L2 Cache" name="Prefetch Allocate" description="Prefetch hint allocated into the L2 cache"/>
     <event event="0xd" title="L2 Cache" name="Speculative Read Received" description="Speculative read received"/>
     <event event="0xe" title="L2 Cache" name="Speculative Read Confirmed" description="Speculative read confirmed"/>
     <event event="0xf" title="L2 Cache" name="Prefetch Hint Received" description="Prefetch hint received"/>
index 62a7018d038f733ee9e67a56828318ca10a59815..0350c0c4b57bb9e8f5623b5d5e1ea9582e4d5e57 100644 (file)
@@ -11,7 +11,7 @@
     <event counter="Linux_meminfo_memfree" title="Memory" name="Free" class="absolute" display="minimum" units="B" description="Available memory size"/>
     <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" class="absolute" units="B" description="Memory used by OS disk buffers"/>
     <event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" class="absolute" units="Hz" series_composition="overlay" average_cores="yes" description="Frequency setting of the CPU"/>
-    <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x003c96fb" description="One or more threads are runnable but waiting due to CPU contention"/>
-    <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x00b30000" description="One or more threads are blocked on an I/O resource"/>
+    <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" multiplier="0.0001" color="0x003c96fb" description="One or more threads are runnable but waiting due to CPU contention"/>
+    <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" multiplier="0.0001" color="0x00b30000" description="One or more threads are blocked on an I/O resource"/>
     <event counter="Linux_power_cpu" title="CPU Status" name="Activity" class="activity" activity1="Off" activity_color1="0x0000ff00" activity2="WFI" activity_color2="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="CPU Status"/>
   </category>
index 0a95dfeb64855910097c3c186a02fcd71e7d166b..801dd28903a875e7c044e54eb357eb2a278df056 100644 (file)
     <event counter="ARM_Mali-4xx_Voltage" title="Mali GPU Voltage" name="Voltage" class="absolute" display="average" average_selection="yes" units="mV" description="GPU core voltage."/>
   </category>
   <category name="ARM_Mali-4xx_Frequency" per_cpu="no">
-    <event counter="ARM_Mali-4xx_Frequency" title="Mali GPU Frequency" name="Frequency" display="average" average_selection="yes" units="MHz" description="GPU core frequency."/>
+    <event counter="ARM_Mali-4xx_Frequency" title="Mali GPU Frequency" name="Frequency" class="absolute" display="average" average_selection="yes" units="MHz" description="GPU core frequency."/>
   </category>
-  <category name="Mali-4xx Activity" counter_set="ARM_Mali-4xx_Activity_cnt">
+  <category name="Mali-4xx Activity" counter_set="ARM_Mali-4xx_Activity_cnt" per_cpu="yes">
     <event counter="ARM_Mali-4xx_fragment" title="GPU Fragment" name="Activity" class="activity" activity1="Activity" activity_color1="0x00006fcc" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="GPU Fragment Activity"/>
     <event counter="ARM_Mali-4xx_vertex" title="GPU Vertex" name="Activity" class="activity" activity1="Activity" activity_color1="0x00eda000" rendering_type="bar" average_selection="yes" percentage="yes" description="GPU Vertex Activity"/>
   </category>
index b6ab4b88cd2edafb01f470f9c87f78ec99ee9eff..33c1a406225df9e35202cab12ce8f3226c212d54 100644 (file)
@@ -1,6 +1,8 @@
   <category name="Mali-Midgard Software Counters" per_cpu="no">
     <event counter="ARM_Mali-Midgard_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
   </category>
+<!--
+power management is disabled during profiling so these counters are not useful as they always return zero
   <category name="Mali-Midgard PM Shader" per_cpu="no">
     <event counter="ARM_Mali-Midgard_PM_SHADER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
     <event counter="ARM_Mali-Midgard_PM_SHADER_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
     <event counter="ARM_Mali-Midgard_PM_SHADER_7" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
   </category>
   <category name="Mali-Midgard PM Tiler" per_cpu="no">
-    <event counter="ARM_Mali-Midgard_PM_TILER_0" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
+    <event counter="ARM_Mali-Midgard_PM_TILER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
   </category>
   <category name="Mali-Midgard PM L2" per_cpu="no">
-    <event counter="ARM_Mali-Midgard_PM_L2_0" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
-    <event counter="ARM_Mali-Midgard_PM_L2_1" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
+    <event counter="ARM_Mali-Midgard_PM_L2_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
+    <event counter="ARM_Mali-Midgard_PM_L2_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
   </category>
+-->
   <category name="Mali-Midgard MMU Address Space" per_cpu="no">
-    <event counter="ARM_Mali-Midgard_MMU_AS_0" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
-    <event counter="ARM_Mali-Midgard_MMU_AS_1" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
-    <event counter="ARM_Mali-Midgard_MMU_AS_2" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
-    <event counter="ARM_Mali-Midgard_MMU_AS_3" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
+    <event counter="ARM_Mali-Midgard_MMU_AS_0" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
+    <event counter="ARM_Mali-Midgard_MMU_AS_1" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
+    <event counter="ARM_Mali-Midgard_MMU_AS_2" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
+    <event counter="ARM_Mali-Midgard_MMU_AS_3" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
   </category>
   <category name="Mali-Midgard MMU Page Fault" per_cpu="no">
     <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
index 4f3323f197d7828366153906464cd755926f01b3..e8f0cb01c1232256db6869032859b6dd8bfadf8b 100644 (file)
@@ -1,15 +1,18 @@
+<!-- this file is valid for Midgard r4p0 and earlier and replaced with the core-specific files in r5p0 -->
   <category name="Mali-Midgard Job Manager" per_cpu="no">
     <event counter="ARM_Mali-Midgard_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles the GPU was active"/>
     <event counter="ARM_Mali-Midgard_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles the GPU had a pending interrupt"/>
     <event counter="ARM_Mali-Midgard_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) was active"/>
     <event counter="ARM_Mali-Midgard_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) was active"/>
     <event counter="ARM_Mali-Midgard_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) was active"/>
-    <event counter="ARM_Mali-Midgard_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
-    <event counter="ARM_Mali-Midgard_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
-    <event counter="ARM_Mali-Midgard_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
-    <event counter="ARM_Mali-Midgard_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
-    <event counter="ARM_Mali-Midgard_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
-    <event counter="ARM_Mali-Midgard_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-Midgard_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-Midgard_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-Midgard_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-Midgard_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-Midgard_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-Midgard_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
   </category>
   <category name="Mali-Midgard Tiler" per_cpu="no">
     <event counter="ARM_Mali-Midgard_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
     <event counter="ARM_Mali-Midgard_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
     <event counter="ARM_Mali-Midgard_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
     <event counter="ARM_Mali-Midgard_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
     <event counter="ARM_Mali-Midgard_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
     <event counter="ARM_Mali-Midgard_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
     <event counter="ARM_Mali-Midgard_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
     <event counter="ARM_Mali-Midgard_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
     <event counter="ARM_Mali-Midgard_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
     <event counter="ARM_Mali-Midgard_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
     <event counter="ARM_Mali-Midgard_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
     <event counter="ARM_Mali-Midgard_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
     <event counter="ARM_Mali-Midgard_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
     <event counter="ARM_Mali-Midgard_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
     <event counter="ARM_Mali-Midgard_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_1" title="Mali Tiler Commands" name="Prims in 1 command" description="Number of primitives producing 1 command"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_2" title="Mali Tiler Commands" name="Prims in 2 command" description="Number of primitives producing 2 commands"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_3" title="Mali Tiler Commands" name="Prims in 3 command" description="Number of primitives producing 3 commands"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_4" title="Mali Tiler Commands" name="Prims in 4 command" description="Number of primitives producing 4 commands"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_4_7" title="Mali Tiler Commands" name="Prims in 4-7 commands" description="Number of primitives producing 4-7 commands"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_5_7" title="Mali Tiler Commands" name="Prims in 5-7 commands" description="Number of primitives producing 5-7 commands"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_8_15" title="Mali Tiler Commands" name="Prims in 8-15 commands" description="Number of primitives producing 8-15 commands"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_16_63" title="Mali Tiler Commands" name="Prims in 16-63 commands" description="Number of primitives producing 16-63 commands"/>
-    <event counter="ARM_Mali-Midgard_COMMAND_64" title="Mali Tiler Commands" name="Prims in &gt;= 64 commands" description="Number of primitives producing &gt;= 64 commands"/>
   </category>
   <category name="Mali-Midgard Shader Core" per_cpu="no">
     <event counter="ARM_Mali-Midgard_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles the Tripipe was active"/>
     <event counter="ARM_Mali-Midgard_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
     <event counter="ARM_Mali-Midgard_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
     <event counter="ARM_Mali-Midgard_FRAG_CYCLE_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+
     <event counter="ARM_Mali-Midgard_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
     <event counter="ARM_Mali-Midgard_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
-    <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
-    <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
+    <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS quads" description="Number of threads doing late ZS test"/>
+    <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS quads" description="Number of threads killed by late ZS test"/>
     <event counter="ARM_Mali-Midgard_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
     <event counter="ARM_Mali-Midgard_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
     <event counter="ARM_Mali-Midgard_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
     <event counter="ARM_Mali-Midgard_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
     <event counter="ARM_Mali-Midgard_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
+
     <event counter="ARM_Mali-Midgard_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
     <event counter="ARM_Mali-Midgard_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
     <event counter="ARM_Mali-Midgard_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
     <event counter="ARM_Mali-Midgard_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
     <event counter="ARM_Mali-Midgard_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
     <event counter="ARM_Mali-Midgard_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
     <event counter="ARM_Mali-Midgard_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
     <event counter="ARM_Mali-Midgard_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
     <event counter="ARM_Mali-Midgard_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
     <event counter="ARM_Mali-Midgard_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
     <event counter="ARM_Mali-Midgard_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
     <event counter="ARM_Mali-Midgard_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
     <event counter="ARM_Mali-Midgard_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
     <event counter="ARM_Mali-Midgard_TEX_THREADS" title="Mali Texture Pipe" name="T instruction issues" description="Number of instructions issused to the T-pipe, including restarts"/>
     <event counter="ARM_Mali-Midgard_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
-    <event counter="ARM_Mali-Midgard_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
-    <event counter="ARM_Mali-Midgard_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+    <event counter="ARM_Mali-Midgard_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_READ_MISSES" title="Mali Load/Store Cache Reads" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_WRITE_MISSES" title="Mali Load/Store Cache Writes" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache Atomics" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+    <event counter="ARM_Mali-Midgard_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
   </category>
   <category name="Mali-Midgard L2 and MMU" per_cpu="no">
-    <event counter="ARM_Mali-Midgard_L2_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
-    <event counter="ARM_Mali-Midgard_L2_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
-    <event counter="ARM_Mali-Midgard_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
-    <event counter="ARM_Mali-Midgard_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
-    <event counter="ARM_Mali-Midgard_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
-    <event counter="ARM_Mali-Midgard_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
-    <event counter="ARM_Mali-Midgard_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-Midgard_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-Midgard_L2_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-Midgard_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+
+    <event counter="ARM_Mali-Midgard_L2_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-Midgard_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+
+    <event counter="ARM_Mali-Midgard_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-Midgard_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+    <event counter="ARM_Mali-Midgard_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-Midgard_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
   </category>
index 50797e6492ad13b3d15c85a92bb53dd7c1899efd..c35bcd11d79883cb9276141702fdeaa499eb9556 100644 (file)
@@ -7,12 +7,13 @@
     <event counter="ARM_Mali-T60x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
     <event counter="ARM_Mali-T60x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
 
-    <event counter="ARM_Mali-T60x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
-    <event counter="ARM_Mali-T60x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
-    <event counter="ARM_Mali-T60x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
-    <event counter="ARM_Mali-T60x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
-    <event counter="ARM_Mali-T60x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
-    <event counter="ARM_Mali-T60x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+    <event counter="ARM_Mali-T60x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-T60x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-T60x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-T60x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-T60x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-T60x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
 
   </category>
 
     <event counter="ARM_Mali-T60x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
     <event counter="ARM_Mali-T60x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
 
-    <event counter="ARM_Mali-T60x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
-    <event counter="ARM_Mali-T60x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+    <event counter="ARM_Mali-T60x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T60x_LSC_READ_MISSES" title="Mali Load/Store Cache Reads" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T60x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T60x_LSC_WRITE_MISSES" title="Mali Load/Store Cache Writes" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T60x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T60x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache Atomics" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T60x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-T60x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T60x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
 
   </category>
 
   <category name="Mali L2 Cache" per_cpu="no">
 
-    <event counter="ARM_Mali-T60x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
-    <event counter="ARM_Mali-T60x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
-    <event counter="ARM_Mali-T60x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
-    <event counter="ARM_Mali-T60x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T60x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
-    <event counter="ARM_Mali-T60x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T60x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T60x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T60x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
-    <event counter="ARM_Mali-T60x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
-    <event counter="ARM_Mali-T60x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
-    <event counter="ARM_Mali-T60x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
-    <event counter="ARM_Mali-T60x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+    <event counter="ARM_Mali-T60x_L2_READ_LOOKUP" title="Mali L2 Cache Reads" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+    <event counter="ARM_Mali-T60x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T60x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
 
-  </category>
+    <event counter="ARM_Mali-T60x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T60x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T60x_L2_WRITE_LOOKUP" title="Mali L2 Cache Writes" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+    <event counter="ARM_Mali-T60x_L2_EXT_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T60x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T60x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+    <event counter="ARM_Mali-T60x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+
+    <event counter="ARM_Mali-T60x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T60x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T60x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache Ext Writes" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+
+  </category>
\ No newline at end of file
index 6ecc53c2ada12d77e88f48b7fa3cee8cc477290b..4bc93068f75bba91b44d483452a1c5c83cf42515 100644 (file)
@@ -7,12 +7,13 @@
     <event counter="ARM_Mali-T62x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
     <event counter="ARM_Mali-T62x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
 
-    <event counter="ARM_Mali-T62x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
-    <event counter="ARM_Mali-T62x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
-    <event counter="ARM_Mali-T62x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
-    <event counter="ARM_Mali-T62x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
-    <event counter="ARM_Mali-T62x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
-    <event counter="ARM_Mali-T62x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+    <event counter="ARM_Mali-T62x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-T62x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-T62x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-T62x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-T62x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-T62x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
 
   </category>
 
     <event counter="ARM_Mali-T62x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
     <event counter="ARM_Mali-T62x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
 
-    <event counter="ARM_Mali-T62x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
-    <event counter="ARM_Mali-T62x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+    <event counter="ARM_Mali-T62x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T62x_LSC_READ_MISSES" title="Mali Load/Store Cache Reads" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T62x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T62x_LSC_WRITE_MISSES" title="Mali Load/Store Cache Writes" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T62x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T62x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache Atomics" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T62x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-T62x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+    <event counter="ARM_Mali-T62x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
 
   </category>
 
   <category name="Mali L2 Cache" per_cpu="no">
 
-    <event counter="ARM_Mali-T62x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
-    <event counter="ARM_Mali-T62x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
-    <event counter="ARM_Mali-T62x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
-    <event counter="ARM_Mali-T62x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T62x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
-    <event counter="ARM_Mali-T62x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T62x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T62x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T62x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
-    <event counter="ARM_Mali-T62x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
-    <event counter="ARM_Mali-T62x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
-    <event counter="ARM_Mali-T62x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
-    <event counter="ARM_Mali-T62x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+    <event counter="ARM_Mali-T62x_L2_READ_LOOKUP" title="Mali L2 Cache Reads" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+    <event counter="ARM_Mali-T62x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T62x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
 
-  </category>
+    <event counter="ARM_Mali-T62x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T62x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T62x_L2_WRITE_LOOKUP" title="Mali L2 Cache Writes" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+    <event counter="ARM_Mali-T62x_L2_EXT_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T62x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T62x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+    <event counter="ARM_Mali-T62x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+
+    <event counter="ARM_Mali-T62x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T62x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T62x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache Ext Writes" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+
+  </category>
\ No newline at end of file
index 5587534770c864abeac9cf51d3e6f64a0dc93b5e..fd9cb0f16c6e688f328886068ed499b5781dbac5 100644 (file)
@@ -7,12 +7,13 @@
     <event counter="ARM_Mali-T72x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
     <event counter="ARM_Mali-T72x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
 
-    <event counter="ARM_Mali-T72x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
-    <event counter="ARM_Mali-T72x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
-    <event counter="ARM_Mali-T72x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
-    <event counter="ARM_Mali-T72x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
-    <event counter="ARM_Mali-T72x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
-    <event counter="ARM_Mali-T72x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+    <event counter="ARM_Mali-T72x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-T72x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-T72x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-T72x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-T72x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-T72x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
 
   </category>
 
     <event counter="ARM_Mali-T72x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
     <event counter="ARM_Mali-T72x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
 
-    <event counter="ARM_Mali-T72x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
-    <event counter="ARM_Mali-T72x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T72x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T72x_LSC_READ_MISSES" title="Mali Load/Store Cache Reads" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T72x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T72x_LSC_WRITE_MISSES" title="Mali Load/Store Cache Writes" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T72x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+    <event counter="ARM_Mali-T72x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache Atomics" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T72x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-T72x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+    <event counter="ARM_Mali-T72x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
 
   </category>
 
   <category name="Mali L2 Cache" per_cpu="no">
 
-    <event counter="ARM_Mali-T72x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
-    <event counter="ARM_Mali-T72x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
-    <event counter="ARM_Mali-T72x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
-    <event counter="ARM_Mali-T72x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T72x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
-    <event counter="ARM_Mali-T72x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T72x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T72x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T72x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
-    <event counter="ARM_Mali-T72x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+    <event counter="ARM_Mali-T72x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T72x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+
+    <event counter="ARM_Mali-T72x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T72x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+
+    <event counter="ARM_Mali-T72x_L2_EXT_READ_BEAT" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T72x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+
+    <event counter="ARM_Mali-T72x_L2_EXT_WRITE_BEAT" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T72x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
 
   </category>
index be74c5a4262431ac0512a57a8f94eb4226fc9abf..94d059fc09dd0000e00498c7704599ca15f2b548 100644 (file)
@@ -7,12 +7,13 @@
     <event counter="ARM_Mali-T76x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
     <event counter="ARM_Mali-T76x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
 
-    <event counter="ARM_Mali-T76x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
-    <event counter="ARM_Mali-T76x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
-    <event counter="ARM_Mali-T76x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
-    <event counter="ARM_Mali-T76x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
-    <event counter="ARM_Mali-T76x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
-    <event counter="ARM_Mali-T76x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+    <event counter="ARM_Mali-T76x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-T76x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-T76x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-T76x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-T76x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-T76x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
 
   </category>
 
     <event counter="ARM_Mali-T76x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
     <event counter="ARM_Mali-T76x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
 
-    <event counter="ARM_Mali-T76x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
-    <event counter="ARM_Mali-T76x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+    <event counter="ARM_Mali-T76x_LSC_READ_OP" title="Mali Load/Store Cache Reads" name="Read operations" description="Number of read operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T76x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T76x_LSC_WRITE_OP" title="Mali Load/Store Cache Writes" name="Write operations" description="Number of write operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T76x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T76x_LSC_ATOMIC_OP" title="Mali Load/Store Cache Atomics" name="Atomic operations" description="Number of atomic operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T76x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T76x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-T76x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T76x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
 
   </category>
 
   <category name="Mali L2 Cache" per_cpu="no">
 
-    <event counter="ARM_Mali-T76x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
-    <event counter="ARM_Mali-T76x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
-    <event counter="ARM_Mali-T76x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
-    <event counter="ARM_Mali-T76x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T76x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
-    <event counter="ARM_Mali-T76x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
-    <event counter="ARM_Mali-T76x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T76x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
-    <event counter="ARM_Mali-T76x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
-    <event counter="ARM_Mali-T76x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
-    <event counter="ARM_Mali-T76x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
-    <event counter="ARM_Mali-T76x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
-    <event counter="ARM_Mali-T76x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
-  </category>
+    <event counter="ARM_Mali-T76x_L2_READ_LOOKUP" title="Mali L2 Cache Reads" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+    <event counter="ARM_Mali-T76x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T76x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+
+    <event counter="ARM_Mali-T76x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T76x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T76x_L2_WRITE_LOOKUP" title="Mali L2 Cache Writes" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+    <event counter="ARM_Mali-T76x_L2_EXT_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T76x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T76x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+    <event counter="ARM_Mali-T76x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+
+    <event counter="ARM_Mali-T76x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T76x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T76x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache Ext Writes" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+
+  </category>
\ No newline at end of file
diff --git a/tools/gator/daemon/events-Mali-T82x_hw.xml b/tools/gator/daemon/events-Mali-T82x_hw.xml
new file mode 100644 (file)
index 0000000..5caa464
--- /dev/null
@@ -0,0 +1,108 @@
+\r
+  <category name="Mali Job Manager" per_cpu="no">\r
+\r
+    <event counter="ARM_Mali-T82x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>\r
+    <event counter="ARM_Mali-T82x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>\r
+    <event counter="ARM_Mali-T82x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>\r
+    <event counter="ARM_Mali-T82x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>\r
+    <event counter="ARM_Mali-T82x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>\r
+\r
+    <event counter="ARM_Mali-T82x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>\r
+    <event counter="ARM_Mali-T82x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>\r
+    <event counter="ARM_Mali-T82x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>\r
+\r
+    <event counter="ARM_Mali-T82x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>\r
+    <event counter="ARM_Mali-T82x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>\r
+    <event counter="ARM_Mali-T82x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>\r
+\r
+  </category>\r
+\r
+  <category name="Mali Tiler" per_cpu="no">\r
+\r
+    <event counter="ARM_Mali-T82x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>\r
+\r
+    <event counter="ARM_Mali-T82x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>\r
+    <event counter="ARM_Mali-T82x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>\r
+    <event counter="ARM_Mali-T82x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>\r
+    <event counter="ARM_Mali-T82x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>\r
+    <event counter="ARM_Mali-T82x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>\r
+\r
+    <event counter="ARM_Mali-T82x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>\r
+    <event counter="ARM_Mali-T82x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>\r
+    <event counter="ARM_Mali-T82x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>\r
+    <event counter="ARM_Mali-T82x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>\r
+    <event counter="ARM_Mali-T82x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>\r
+\r
+  </category>\r
+\r
+  <category name="Mali Shader Core" per_cpu="no">\r
+\r
+    <event counter="ARM_Mali-T82x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>\r
+    <event counter="ARM_Mali-T82x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>\r
+\r
+    <event counter="ARM_Mali-T82x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>\r
+\r
+    <event counter="ARM_Mali-T82x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>\r
+    <event counter="ARM_Mali-T82x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>\r
+\r
+    <event counter="ARM_Mali-T82x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>\r
+\r
+    <event counter="ARM_Mali-T82x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>\r
+\r
+    <event counter="ARM_Mali-T82x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>\r
+    <event counter="ARM_Mali-T82x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>\r
+\r
+    <event counter="ARM_Mali-T82x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of batched instructions executed by the A-pipe (normalized per pipe)"/>\r
+\r
+    <event counter="ARM_Mali-T82x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>\r
+    <event counter="ARM_Mali-T82x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>\r
+\r
+    <event counter="ARM_Mali-T82x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>\r
+    <event counter="ARM_Mali-T82x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>\r
+    <event counter="ARM_Mali-T82x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>\r
+\r
+    <event counter="ARM_Mali-T82x_LSC_READ_OP" title="Mali Load/Store Cache Reads" name="Read operations" description="Number of read operations in the Load/Store cache"/>\r
+    <event counter="ARM_Mali-T82x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>\r
+\r
+    <event counter="ARM_Mali-T82x_LSC_WRITE_OP" title="Mali Load/Store Cache Writes" name="Write operations" description="Number of write operations in the Load/Store cache"/>\r
+    <event counter="ARM_Mali-T82x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>\r
+\r
+    <event counter="ARM_Mali-T82x_LSC_ATOMIC_OP" title="Mali Load/Store Cache Atomics" name="Atomic operations" description="Number of atomic operations in the Load/Store cache"/>\r
+    <event counter="ARM_Mali-T82x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>\r
+\r
+    <event counter="ARM_Mali-T82x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>\r
+    <event counter="ARM_Mali-T82x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>\r
+\r
+    <event counter="ARM_Mali-T82x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>\r
+\r
+  </category>\r
+\r
+  <category name="Mali L2 Cache" per_cpu="no">\r
+\r
+    <event counter="ARM_Mali-T82x_L2_READ_LOOKUP" title="Mali L2 Cache Reads" name="L2 read lookups" description="Number of reads into the L2 cache"/>\r
+    <event counter="ARM_Mali-T82x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>\r
+    <event counter="ARM_Mali-T82x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>\r
+\r
+    <event counter="ARM_Mali-T82x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>\r
+    <event counter="ARM_Mali-T82x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>\r
+    <event counter="ARM_Mali-T82x_L2_WRITE_LOOKUP" title="Mali L2 Cache Writes" name="L2 write lookups" description="Number of writes into the L2 cache"/>\r
+\r
+    <event counter="ARM_Mali-T82x_L2_EXT_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>\r
+    <event counter="ARM_Mali-T82x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>\r
+    <event counter="ARM_Mali-T82x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>\r
+    <event counter="ARM_Mali-T82x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>\r
+\r
+    <event counter="ARM_Mali-T82x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>\r
+    <event counter="ARM_Mali-T82x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>\r
+    <event counter="ARM_Mali-T82x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache Ext Writes" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>\r
+\r
+  </category>\r
diff --git a/tools/gator/daemon/events-Mali-T83x_hw.xml b/tools/gator/daemon/events-Mali-T83x_hw.xml
new file mode 100644 (file)
index 0000000..39f7acf
--- /dev/null
@@ -0,0 +1,108 @@
+
+  <category name="Mali Job Manager" per_cpu="no">
+
+    <event counter="ARM_Mali-T83x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+    <event counter="ARM_Mali-T83x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+    <event counter="ARM_Mali-T83x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+    <event counter="ARM_Mali-T83x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+    <event counter="ARM_Mali-T83x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+    <event counter="ARM_Mali-T83x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-T83x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-T83x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-T83x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-T83x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-T83x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+
+  </category>
+
+  <category name="Mali Tiler" per_cpu="no">
+
+    <event counter="ARM_Mali-T83x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+    <event counter="ARM_Mali-T83x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+    <event counter="ARM_Mali-T83x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+    <event counter="ARM_Mali-T83x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+    <event counter="ARM_Mali-T83x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+    <event counter="ARM_Mali-T83x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+    <event counter="ARM_Mali-T83x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+    <event counter="ARM_Mali-T83x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+    <event counter="ARM_Mali-T83x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+    <event counter="ARM_Mali-T83x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+    <event counter="ARM_Mali-T83x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+  </category>
+
+  <category name="Mali Shader Core" per_cpu="no">
+
+    <event counter="ARM_Mali-T83x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+    <event counter="ARM_Mali-T83x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+    <event counter="ARM_Mali-T83x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+    <event counter="ARM_Mali-T83x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+    <event counter="ARM_Mali-T83x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>
+
+    <event counter="ARM_Mali-T83x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+    <event counter="ARM_Mali-T83x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+    <event counter="ARM_Mali-T83x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+    <event counter="ARM_Mali-T83x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+    <event counter="ARM_Mali-T83x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+    <event counter="ARM_Mali-T83x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+    <event counter="ARM_Mali-T83x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+    <event counter="ARM_Mali-T83x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+    <event counter="ARM_Mali-T83x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+    <event counter="ARM_Mali-T83x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+    <event counter="ARM_Mali-T83x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+    <event counter="ARM_Mali-T83x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+    <event counter="ARM_Mali-T83x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+    <event counter="ARM_Mali-T83x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of batched instructions executed by the A-pipe (normalized per pipe)"/>
+
+    <event counter="ARM_Mali-T83x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+    <event counter="ARM_Mali-T83x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+    <event counter="ARM_Mali-T83x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+    <event counter="ARM_Mali-T83x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+    <event counter="ARM_Mali-T83x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+    <event counter="ARM_Mali-T83x_LSC_READ_OP" title="Mali Load/Store Cache Reads" name="Read operations" description="Number of read operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T83x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T83x_LSC_WRITE_OP" title="Mali Load/Store Cache Writes" name="Write operations" description="Number of write operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T83x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T83x_LSC_ATOMIC_OP" title="Mali Load/Store Cache Atomics" name="Atomic operations" description="Number of atomic operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T83x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T83x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-T83x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T83x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+  </category>
+
+  <category name="Mali L2 Cache" per_cpu="no">
+
+    <event counter="ARM_Mali-T83x_L2_READ_LOOKUP" title="Mali L2 Cache Reads" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+    <event counter="ARM_Mali-T83x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T83x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+
+    <event counter="ARM_Mali-T83x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T83x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T83x_L2_WRITE_LOOKUP" title="Mali L2 Cache Writes" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+    <event counter="ARM_Mali-T83x_L2_EXT_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T83x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T83x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+    <event counter="ARM_Mali-T83x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+
+    <event counter="ARM_Mali-T83x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T83x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T83x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache Ext Writes" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+
+  </category>
diff --git a/tools/gator/daemon/events-Mali-T86x_hw.xml b/tools/gator/daemon/events-Mali-T86x_hw.xml
new file mode 100644 (file)
index 0000000..6653543
--- /dev/null
@@ -0,0 +1,117 @@
+
+  <category name="Mali Job Manager" per_cpu="no">
+
+    <event counter="ARM_Mali-T86x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+    <event counter="ARM_Mali-T86x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+    <event counter="ARM_Mali-T86x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+    <event counter="ARM_Mali-T86x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+    <event counter="ARM_Mali-T86x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+    <event counter="ARM_Mali-T86x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-T86x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-T86x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-T86x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-T86x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-T86x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+
+  </category>
+
+  <category name="Mali Tiler" per_cpu="no">
+
+    <event counter="ARM_Mali-T86x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+    <event counter="ARM_Mali-T86x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+    <event counter="ARM_Mali-T86x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+    <event counter="ARM_Mali-T86x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+    <event counter="ARM_Mali-T86x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+    <event counter="ARM_Mali-T86x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+    <event counter="ARM_Mali-T86x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+    <event counter="ARM_Mali-T86x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+    <event counter="ARM_Mali-T86x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+    <event counter="ARM_Mali-T86x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+    <event counter="ARM_Mali-T86x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+    <event counter="ARM_Mali-T86x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+    <event counter="ARM_Mali-T86x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+    <event counter="ARM_Mali-T86x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+    <event counter="ARM_Mali-T86x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+    <event counter="ARM_Mali-T86x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+    <event counter="ARM_Mali-T86x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+    <event counter="ARM_Mali-T86x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+    <event counter="ARM_Mali-T86x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+  </category>
+
+  <category name="Mali Shader Core" per_cpu="no">
+
+    <event counter="ARM_Mali-T86x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+    <event counter="ARM_Mali-T86x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+    <event counter="ARM_Mali-T86x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+    <event counter="ARM_Mali-T86x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+    <event counter="ARM_Mali-T86x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>
+
+    <event counter="ARM_Mali-T86x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+    <event counter="ARM_Mali-T86x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+    <event counter="ARM_Mali-T86x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+    <event counter="ARM_Mali-T86x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+    <event counter="ARM_Mali-T86x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+    <event counter="ARM_Mali-T86x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+    <event counter="ARM_Mali-T86x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+    <event counter="ARM_Mali-T86x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+    <event counter="ARM_Mali-T86x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+    <event counter="ARM_Mali-T86x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+    <event counter="ARM_Mali-T86x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+    <event counter="ARM_Mali-T86x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+    <event counter="ARM_Mali-T86x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+    <event counter="ARM_Mali-T86x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+    <event counter="ARM_Mali-T86x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+    <event counter="ARM_Mali-T86x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+    <event counter="ARM_Mali-T86x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+    <event counter="ARM_Mali-T86x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+    <event counter="ARM_Mali-T86x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+    <event counter="ARM_Mali-T86x_LSC_READ_OP" title="Mali Load/Store Cache Reads" name="Read operations" description="Number of read operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T86x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T86x_LSC_WRITE_OP" title="Mali Load/Store Cache Writes" name="Write operations" description="Number of write operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T86x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T86x_LSC_ATOMIC_OP" title="Mali Load/Store Cache Atomics" name="Atomic operations" description="Number of atomic operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T86x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T86x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-T86x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T86x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+  </category>
+
+  <category name="Mali L2 Cache" per_cpu="no">
+
+    <event counter="ARM_Mali-T86x_L2_READ_LOOKUP" title="Mali L2 Cache Reads" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+    <event counter="ARM_Mali-T86x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T86x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+
+    <event counter="ARM_Mali-T86x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T86x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T86x_L2_WRITE_LOOKUP" title="Mali L2 Cache Writes" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+    <event counter="ARM_Mali-T86x_L2_EXT_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T86x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T86x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+    <event counter="ARM_Mali-T86x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+
+    <event counter="ARM_Mali-T86x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T86x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T86x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache Ext Writes" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+
+  </category>
diff --git a/tools/gator/daemon/events-Mali-T88x_hw.xml b/tools/gator/daemon/events-Mali-T88x_hw.xml
new file mode 100644 (file)
index 0000000..19385d1
--- /dev/null
@@ -0,0 +1,117 @@
+
+  <category name="Mali Job Manager" per_cpu="no">
+
+    <event counter="ARM_Mali-T88x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+    <event counter="ARM_Mali-T88x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+    <event counter="ARM_Mali-T88x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+    <event counter="ARM_Mali-T88x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+    <event counter="ARM_Mali-T88x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+    <event counter="ARM_Mali-T88x_JS0_JOBS" title="Mali Job Manager Jobs" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+    <event counter="ARM_Mali-T88x_JS1_JOBS" title="Mali Job Manager Jobs" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+    <event counter="ARM_Mali-T88x_JS2_JOBS" title="Mali Job Manager Jobs" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+    <event counter="ARM_Mali-T88x_JS0_TASKS" title="Mali Job Manager Tasks" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+    <event counter="ARM_Mali-T88x_JS1_TASKS" title="Mali Job Manager Tasks" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+    <event counter="ARM_Mali-T88x_JS2_TASKS" title="Mali Job Manager Tasks" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+
+  </category>
+
+  <category name="Mali Tiler" per_cpu="no">
+
+    <event counter="ARM_Mali-T88x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+    <event counter="ARM_Mali-T88x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+    <event counter="ARM_Mali-T88x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+    <event counter="ARM_Mali-T88x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+    <event counter="ARM_Mali-T88x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+    <event counter="ARM_Mali-T88x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+    <event counter="ARM_Mali-T88x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+    <event counter="ARM_Mali-T88x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+    <event counter="ARM_Mali-T88x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+    <event counter="ARM_Mali-T88x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+    <event counter="ARM_Mali-T88x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+    <event counter="ARM_Mali-T88x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+    <event counter="ARM_Mali-T88x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+    <event counter="ARM_Mali-T88x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+    <event counter="ARM_Mali-T88x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+    <event counter="ARM_Mali-T88x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+    <event counter="ARM_Mali-T88x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+    <event counter="ARM_Mali-T88x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+    <event counter="ARM_Mali-T88x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+  </category>
+
+  <category name="Mali Shader Core" per_cpu="no">
+
+    <event counter="ARM_Mali-T88x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+    <event counter="ARM_Mali-T88x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+    <event counter="ARM_Mali-T88x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+    <event counter="ARM_Mali-T88x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+    <event counter="ARM_Mali-T88x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>
+
+    <event counter="ARM_Mali-T88x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+    <event counter="ARM_Mali-T88x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+    <event counter="ARM_Mali-T88x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+    <event counter="ARM_Mali-T88x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+    <event counter="ARM_Mali-T88x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+    <event counter="ARM_Mali-T88x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+    <event counter="ARM_Mali-T88x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+    <event counter="ARM_Mali-T88x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+    <event counter="ARM_Mali-T88x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+    <event counter="ARM_Mali-T88x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+    <event counter="ARM_Mali-T88x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+    <event counter="ARM_Mali-T88x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+    <event counter="ARM_Mali-T88x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+    <event counter="ARM_Mali-T88x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+    <event counter="ARM_Mali-T88x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+    <event counter="ARM_Mali-T88x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+    <event counter="ARM_Mali-T88x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+    <event counter="ARM_Mali-T88x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+    <event counter="ARM_Mali-T88x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+    <event counter="ARM_Mali-T88x_LSC_READ_OP" title="Mali Load/Store Cache Reads" name="Read operations" description="Number of read operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T88x_LSC_READ_HITS" title="Mali Load/Store Cache Reads" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T88x_LSC_WRITE_OP" title="Mali Load/Store Cache Writes" name="Write operations" description="Number of write operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T88x_LSC_WRITE_HITS" title="Mali Load/Store Cache Writes" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T88x_LSC_ATOMIC_OP" title="Mali Load/Store Cache Atomics" name="Atomic operations" description="Number of atomic operations in the Load/Store cache"/>
+    <event counter="ARM_Mali-T88x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache Atomics" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T88x_LSC_LINE_FETCHES" title="Mali Load/Store Cache Bus" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+    <event counter="ARM_Mali-T88x_LSC_DIRTY_LINE" title="Mali Load/Store Cache Bus" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+
+    <event counter="ARM_Mali-T88x_LSC_SNOOPS" title="Mali Load/Store Cache Bus" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+  </category>
+
+  <category name="Mali L2 Cache" per_cpu="no">
+
+    <event counter="ARM_Mali-T88x_L2_READ_LOOKUP" title="Mali L2 Cache Reads" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+    <event counter="ARM_Mali-T88x_L2_READ_SNOOP" title="Mali L2 Cache Reads" name="Read snoops" description="Number of read transaction snoops"/>
+    <event counter="ARM_Mali-T88x_L2_READ_HIT" title="Mali L2 Cache Reads" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+
+    <event counter="ARM_Mali-T88x_L2_WRITE_SNOOP" title="Mali L2 Cache Writes" name="Write snoops" description="Number of write transaction snoops"/>
+    <event counter="ARM_Mali-T88x_L2_WRITE_HIT" title="Mali L2 Cache Writes" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+    <event counter="ARM_Mali-T88x_L2_WRITE_LOOKUP" title="Mali L2 Cache Writes" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+    <event counter="ARM_Mali-T88x_L2_EXT_READ_BEATS" title="Mali L2 Cache Ext Reads" name="External read beats" description="Number of external bus read beats"/>
+    <event counter="ARM_Mali-T88x_L2_EXT_AR_STALL" title="Mali L2 Cache Ext Reads" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T88x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+    <event counter="ARM_Mali-T88x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache Ext Reads" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+
+    <event counter="ARM_Mali-T88x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache Ext Writes" name="External write beats" description="Number of external bus write beats"/>
+    <event counter="ARM_Mali-T88x_L2_EXT_W_STALL" title="Mali L2 Cache Ext Writes" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+    <event counter="ARM_Mali-T88x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache Ext Writes" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+
+  </category>
diff --git a/tools/gator/daemon/events-Other.xml b/tools/gator/daemon/events-Other.xml
new file mode 100644 (file)
index 0000000..8aec282
--- /dev/null
@@ -0,0 +1,33 @@
+  <counter_set name="Other_cnt" count="6"/>
+  <category name="Other" counter_set="Other_cnt" per_cpu="yes" supports_event_based_sampling="yes">
+    <event counter="Other_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
+    <event event="0x00" title="Software" name="Increment" description="Instruction architecturally executed, condition code check pass, software increment"/>
+    <event event="0x01" title="Cache" name="Instruction refill" description="Level 1 instruction cache refill"/>
+    <event event="0x02" title="Cache" name="Inst TLB refill" description="Level 1 instruction TLB refill"/>
+    <event event="0x03" title="Cache" name="Data refill" description="Level 1 data cache refill"/>
+    <event event="0x04" title="Cache" name="Data access" description="Level 1 data cache access"/>
+    <event event="0x05" title="Cache" name="Data TLB refill" description="Level 1 data TLB refill"/>
+    <event event="0x06" title="Instruction" name="Memory read" description="Instruction architecturally executed, condition code check pass, load"/>
+    <event event="0x07" title="Instruction" name="Memory write" description="Instruction architecturally executed, condition code check pass, store"/>
+    <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
+    <event event="0x09" title="Exception" name="Taken" description="Exception taken"/>
+    <event event="0x0a" title="Exception" name="Return" description="Instruction architecturally executed, condition code check pass, exception return"/>
+    <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction architecturally executed, condition code check pass, write to CONTEXTIDR"/>
+    <event event="0x0c" title="Branch" name="PC change" description="Instruction architecturally executed, condition code check pass, software change of the PC"/>
+    <event event="0x0d" title="Branch" name="Immediate" description="Instruction architecturally executed, immediate branch"/>
+    <event event="0x0e" title="Procedure" name="Return" description="Instruction architecturally executed, condition code check pass, procedure return"/>
+    <event event="0x0f" title="Memory" name="Unaligned access" description="Instruction architecturally executed, condition code check pass, unaligned load or store"/>
+    <event event="0x10" title="Branch" name="Mispredicted" description="Mispredicted or not predicted branch speculatively executed"/>
+    <event event="0x12" title="Branch" name="Potential prediction" description="Predictable branch speculatively executed"/>
+    <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
+    <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
+    <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache write-back"/>
+    <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
+    <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
+    <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache write-back"/>
+    <event event="0x19" title="Bus" name="Access" description="Bus access"/>
+    <event event="0x1a" title="Memory" name="Error" description="Local memory error"/>
+    <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
+    <event event="0x1c" title="Memory" name="Translation table" description="Instruction architecturally executed, condition code check pass, write to TTBR"/>
+    <event event="0x1d" title="Bus" name="Cycle" description="Bus cycle"/>
+  </category>
index 33ab7aab21969bff65c2ea16c56c85db5cb95ef2..ae5529f2678dbb692ba8219305a0f66e0a2f45e5 100644 (file)
@@ -1,7 +1,22 @@
   <category name="Ftrace">
-    <!-- counter attribute must start with ftrace_ and be unique -->
-    <!-- regex item in () is the value shown -->
     <!--
-    <event counter="ftrace_trace_marker_numbers" title="ftrace" name="trace_marker" class="absolute" regex="([0-9]+)" description="Numbers written to /sys/kernel/debug/tracing/trace_marker, ex: echo 42 > /sys/kernel/debug/tracing/trace_marker"/>
+       Ftrace counters require Linux 3.10 or later. If you do you see ftrace counters in counter configuration, please check your Linux version.
+       'counter' attribute must start with ftrace_ and be unique
+       the regex item in () is the value shown or, if the parentheses are missing, the number of regex matches is counted
+       'enable' (optional) is the ftrace event to enable associated with the gator event
     -->
+    <!--
+    <event counter="ftrace_trace_marker_numbers" title="ftrace" name="trace_marker" regex="^tracing_mark_write: ([0-9]+)\s$" class="absolute" description="Numbers written to /sys/kernel/debug/tracing/trace_marker, ex: echo 42 > /sys/kernel/debug/tracing/trace_marker"/>
+    -->
+
+    <!-- ftrace counters -->
+    <event counter="ftrace_kmem_kmalloc" title="Kmem" name="kmalloc" regex="^kmalloc:.* bytes_alloc=([0-9]+) " enable="kmem/kmalloc" class="incident" description="Number of bytes allocated in the kernel using kmalloc"/>
+    <event counter="ftrace_ext4_ext4_da_write" title="Ext4" name="ext4_da_write" regex="^ext4_da_write_end:.* len ([0-9]+) " enable="ext4/ext4_da_write_end" class="incident" description="Number of bytes written to an ext4 filesystem"/>
+    <event counter="ftrace_f2fs_f2fs_write" title="F2FS" name="f2fs_write" regex="^f2fs_write_end:.* len ([0-9]+), " enable="f2fs/f2fs_write_end" class="incident" description="Number of bytes written to an f2fs filesystem"/>
+    <event counter="ftrace_power_clock_set_rate" title="Power" name="clock_set_rate" regex="^clock_set_rate:.* state=([0-9]+) " enable="power/clock_set_rate" class="absolute" description="Clock rate state"/>
+
+    <!-- counting ftrace counters -->
+    <event counter="ftrace_block_block_rq_complete" title="Block" name="block_rq_complete" regex="^block_rq_complete: " enable="block/block_rq_complete" class="delta" description="Number of block IO operations completed by device driver"/>
+    <event counter="ftrace_block_block_rq_issue" title="Block" name="block_rq_issue" regex="^block_rq_issue: " enable="block/block_rq_issue" class="delta" description="Number of block IO operations issued to device driver"/>
+    <event counter="ftrace_power_cpu_idle" title="Power" name="cpu_idle" regex="^cpu_idle: " enable="power/cpu_idle" class="delta" description="Number of times cpu_idle is entered or exited"/>
   </category>
index fbce1e15d0d015da52111fb80245e88f84c4ab23..c68a892e74fcd7d256cb23011b67b74fde0508d7 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2015. All rights reserved.
  *
  * 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
@@ -19,6 +19,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include "AnnotateListener.h"
 #include "CCNDriver.h"
 #include "Child.h"
 #include "EventsXML.h"
@@ -133,7 +134,7 @@ public:
                memset(&mDstAns, 0, sizeof(mDstAns));
                memcpy(mDstAns.rviHeader, "STR_ANS ", sizeof(mDstAns.rviHeader));
                if (gethostname(mDstAns.dhcpName, sizeof(mDstAns.dhcpName) - 1) != 0) {
-                       logg->logError(__FILE__, __LINE__, "gethostname failed");
+                       logg->logError("gethostname failed");
                        handleException();
                }
                // Subvert the defaultGateway field for the port number
@@ -156,7 +157,7 @@ public:
                addrlen = sizeof(sockaddr);
                read = recvfrom(mReq, &buf, sizeof(buf), 0, (struct sockaddr *)&sockaddr, &addrlen);
                if (read < 0) {
-                       logg->logError(__FILE__, __LINE__, "recvfrom failed");
+                       logg->logError("recvfrom failed");
                        handleException();
                } else if ((read == 12) && (memcmp(buf, DST_REQ, sizeof(DST_REQ)) == 0)) {
                        // Don't care if sendto fails - gatord shouldn't exit because of it and Streamline will retry
@@ -180,23 +181,29 @@ private:
                        family = AF_INET;
                        s = socket_cloexec(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                        if (s == -1) {
-                               logg->logError(__FILE__, __LINE__, "socket failed");
+                               logg->logError("socket failed");
                                handleException();
                        }
                }
 
                on = 1;
                if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
-                       logg->logError(__FILE__, __LINE__, "setsockopt failed");
+                       logg->logError("setsockopt REUSEADDR failed");
                        handleException();
                }
 
+               // Listen on both IPv4 and IPv6
+               on = 0;
+               if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) != 0) {
+                       logg->logMessage("setsockopt IPV6_V6ONLY failed");
+               }
+
                memset((void*)&sockaddr, 0, sizeof(sockaddr));
                sockaddr.sin6_family = family;
                sockaddr.sin6_port = htons(port);
                sockaddr.sin6_addr = in6addr_any;
                if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) {
-                       logg->logError(__FILE__, __LINE__, "socket failed");
+                       logg->logError("socket failed");
                        handleException();
                }
 
@@ -252,7 +259,7 @@ static bool setupFilesystem(char* module) {
 
                // if still mounted
                if (access("/dev/gator/buffer", F_OK) == 0) {
-                       logg->logError(__FILE__, __LINE__, "Unable to remove the running gator.ko. Manually remove the module or use the running module by not specifying one on the commandline");
+                       logg->logError("Unable to remove the running gator.ko. Manually remove the module or use the running module by not specifying one on the commandline");
                        handleException();
                }
        }
@@ -284,7 +291,7 @@ static bool setupFilesystem(char* module) {
                                return false;
                        } else {
                                // gator location specified on the command line but it was not found
-                               logg->logError(__FILE__, __LINE__, "gator module not found at %s", location);
+                               logg->logError("gator module not found at %s", location);
                                handleException();
                        }
                }
@@ -296,13 +303,13 @@ static bool setupFilesystem(char* module) {
                        snprintf(command, sizeof(command), "insmod %s >/dev/null 2>&1", location);
                        if (system(command) != 0) {
                                logg->logMessage("Unable to load gator.ko driver with command: %s", command);
-                               logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n  >>> gator.ko must be built against the current kernel version & configuration\n  >>> See dmesg for more details");
+                               logg->logError("Unable to load (insmod) gator.ko driver:\n  >>> gator.ko must be built against the current kernel version & configuration\n  >>> See dmesg for more details");
                                handleException();
                        }
                }
 
                if (mountGatorFS() == -1) {
-                       logg->logError(__FILE__, __LINE__, "Unable to mount the gator filesystem needed for profiling.");
+                       logg->logError("Unable to mount the gator filesystem needed for profiling.");
                        handleException();
                }
        }
@@ -326,7 +333,7 @@ static int shutdownFilesystem() {
        return 0; // success
 }
 
-static const char OPTSTRING[] = "hvudap:s:c:e:m:o:";
+static const char OPTSTRING[] = "hvVudap:s:c:e:E:m:o:";
 
 static bool hasDebugFlag(int argc, char** argv) {
        int c;
@@ -368,11 +375,18 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
                        case 'e':
                                gSessionData->mEventsXMLPath = optarg;
                                break;
+                       case 'E':
+                               gSessionData->mEventsXMLAppend = optarg;
+                               break;
                        case 'm':
                                cmdline.module = optarg;
                                break;
                        case 'p':
                                cmdline.port = strtol(optarg, NULL, 10);
+                               if ((cmdline.port == 8082) || (cmdline.port == 8083)) {
+                                       logg->logError("Gator can't use port %i, as it already uses ports 8082 and 8083 for annotations. Please select a different port.", cmdline.port);
+                                       handleException();
+                               }
                                break;
                        case 's':
                                gSessionData->mSessionXMLPath = optarg;
@@ -388,10 +402,11 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
                                break;
                        case 'h':
                        case '?':
-                               logg->logError(__FILE__, __LINE__,
+                               logg->logError(
                                        "%s. All parameters are optional:\n"
-                                       "-c config_xml   path and filename of the configuration.xml to use\n"
-                                       "-e events_xml   path and filename of the events.xml to use\n"
+                                       "-c config_xml   path and filename of the configuration XML to use\n"
+                                       "-e events_xml   path and filename of the events XML to use\n"
+                                       "-E events_xml   path and filename of events XML to append\n"
                                        "-h              this help page\n"
                                        "-m module       path and filename of gator.ko\n"
                                        "-p port_number  port upon which the server listens; default is 8080\n"
@@ -399,12 +414,16 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
                                        "-o apc_dir      path and name of the output for a local capture\n"
                                        "-v              version information\n"
                                        "-d              enable debug messages\n"
-                                       "-a              allow the user user to provide a command to run at the start of a capture"
+                                       "-a              allow the user to issue a command from Streamline"
                                        , version_string);
                                handleException();
                                break;
                        case 'v':
-                               logg->logError(__FILE__, __LINE__, version_string);
+                               logg->logError("%s", version_string);
+                               handleException();
+                               break;
+                       case 'V':
+                               logg->logError("%s\nSRC_MD5: %s", version_string, gSrcMd5);
                                handleException();
                                break;
                }
@@ -412,35 +431,38 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
 
        // Error checking
        if (cmdline.port != DEFAULT_PORT && gSessionData->mSessionXMLPath != NULL) {
-               logg->logError(__FILE__, __LINE__, "Only a port or a session xml can be specified, not both");
+               logg->logError("Only a port or a session xml can be specified, not both");
                handleException();
        }
 
        if (gSessionData->mTargetPath != NULL && gSessionData->mSessionXMLPath == NULL) {
-               logg->logError(__FILE__, __LINE__, "Missing -s command line option required for a local capture.");
+               logg->logError("Missing -s command line option required for a local capture.");
                handleException();
        }
 
        if (optind < argc) {
-               logg->logError(__FILE__, __LINE__, "Unknown argument: %s. Use '-h' for help.", argv[optind]);
+               logg->logError("Unknown argument: %s. Use '-h' for help.", argv[optind]);
                handleException();
        }
 
        return cmdline;
 }
 
+static AnnotateListener annotateListener;
+
 static void handleClient() {
        OlySocket client(sock->acceptConnection());
 
        int pid = fork();
        if (pid < 0) {
                // Error
-               logg->logError(__FILE__, __LINE__, "Fork process failed. Please power cycle the target device if this error persists.");
+               logg->logError("Fork process failed. Please power cycle the target device if this error persists.");
        } else if (pid == 0) {
                // Child
                sock->closeServerSocket();
                udpListener.close();
                monitor.close();
+               annotateListener.close();
                child = new Child(&client, numSessions + 1);
                child->run();
                delete child;
@@ -500,21 +522,23 @@ int main(int argc, char** argv) {
        struct cmdline_t cmdline = parseCommandLine(argc, argv);
 
        if (cmdline.update) {
-               return update(argv[0]);
+               update(argv[0]);
+               cmdline.update = false;
+               gSessionData->mAllowCommands = true;
        }
 
        // Verify root permissions
        uid_t euid = geteuid();
        if (euid) {
-               logg->logError(__FILE__, __LINE__, "gatord must be launched with root privileges");
+               logg->logError("gatord must be launched with root privileges");
                handleException();
        }
 
        // Call before setting up the SIGCHLD handler, as system() spawns child processes
        if (!setupFilesystem(cmdline.module)) {
-               logg->logMessage("Unable to setup gatorfs, trying perf");
+               logg->logMessage("Unable to set up gatorfs, trying perf");
                if (!gSessionData->perf.setup()) {
-                       logg->logError(__FILE__, __LINE__,
+                       logg->logError(
                                       "Unable to locate gator.ko driver:\n"
                                       "  >>> gator.ko should be co-located with gatord in the same directory\n"
                                       "  >>> OR insmod gator.ko prior to launching gatord\n"
@@ -547,15 +571,23 @@ int main(int argc, char** argv) {
                child->run();
                delete child;
        } else {
-               gSessionData->annotateListener.setup();
+               annotateListener.setup();
+               int pipefd[2];
+               if (pipe_cloexec(pipefd) != 0) {
+                       logg->logError("Unable to set up annotate pipe");
+                       handleException();
+               }
+               gSessionData->mAnnotateStart = pipefd[1];
                sock = new OlyServerSocket(cmdline.port);
                udpListener.setup(cmdline.port);
                if (!monitor.init() ||
                                !monitor.add(sock->getFd()) ||
                                !monitor.add(udpListener.getReq()) ||
-                               !monitor.add(gSessionData->annotateListener.getFd()) ||
+                               !monitor.add(annotateListener.getSockFd()) ||
+                               !monitor.add(annotateListener.getUdsFd()) ||
+                               !monitor.add(pipefd[0]) ||
                                false) {
-                       logg->logError(__FILE__, __LINE__, "Monitor setup failed");
+                       logg->logError("Monitor setup failed");
                        handleException();
                }
                // Forever loop, can be exited via a signal or exception
@@ -564,7 +596,7 @@ int main(int argc, char** argv) {
                        logg->logMessage("Waiting on connection...");
                        int ready = monitor.wait(events, ARRAY_LENGTH(events), -1);
                        if (ready < 0) {
-                               logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
+                               logg->logError("Monitor::wait failed");
                                handleException();
                        }
                        for (int i = 0; i < ready; ++i) {
@@ -572,8 +604,16 @@ int main(int argc, char** argv) {
                                        handleClient();
                                } else if (events[i].data.fd == udpListener.getReq()) {
                                        udpListener.handle();
-                               } else if (events[i].data.fd == gSessionData->annotateListener.getFd()) {
-                                       gSessionData->annotateListener.handle();
+                               } else if (events[i].data.fd == annotateListener.getSockFd()) {
+                                       annotateListener.handleSock();
+                               } else if (events[i].data.fd == annotateListener.getUdsFd()) {
+                                       annotateListener.handleUds();
+                               } else if (events[i].data.fd == pipefd[0]) {
+                                       uint64_t val;
+                                       if (read(pipefd[0], &val, sizeof(val)) != sizeof(val)) {
+                                               logg->logMessage("Reading annotate pipe failed");
+                                       }
+                                       annotateListener.signal();
                                }
                        }
                }
index d1b3a361e526d83d1ce011819d917e6f9c256f81..4039854560d0d5dffe32150562a6f11b2791033f 100644 (file)
@@ -1,8 +1,12 @@
 CC             = $(CROSS_COMPILE)gcc
-BUILD_OUTPUT   := $(PWD)
+BUILD_OUTPUT   := $(CURDIR)
 PREFIX         := /usr
 DESTDIR                :=
 
+ifeq ("$(origin O)", "command line")
+       BUILD_OUTPUT := $(O)
+endif
+
 turbostat : turbostat.c
 CFLAGS +=      -Wall
 CFLAGS +=      -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"'
index 4eed4cd9b58b36cc54a9328460db616f2e4e3362..8c56eae63e74b7ff1f557df1175862b8649dadd2 100644 (file)
@@ -1550,8 +1550,8 @@ int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
        ghc->generation = slots->generation;
        ghc->len = len;
        ghc->memslot = gfn_to_memslot(kvm, start_gfn);
-       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
-       if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
+       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, NULL);
+       if (!kvm_is_error_hva(ghc->hva) && nr_pages_needed <= 1) {
                ghc->hva += offset;
        } else {
                /*